powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Поиск и обновление всех вхождений подстроки в строку
13 сообщений из 13, страница 1 из 1
Поиск и обновление всех вхождений подстроки в строку
    #40112894
John__Smit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день. Работаю с Microsoft SQL Server 2005.
Есть таблица вида:
ID DATA FIN_PER
1 a 1:58.57,2:58.59
2 b 10:5.25,11:6.40
3 c 111:8.29,112:7.11,113:4.41
4 d 12:16.25

в которой столбец FIN_PER представляет собой остаток средств по периодам.
То что находится перед символом ":" это период (который может быть представлен одним,двумя,тремя знаками)
То что находится после символа ":" до символа "," либо до конца строки - это собственно остаток средств
Периодов в строке может быть очень много (грубо до 100 периодов)

Задача прибавить к каждому периоду @x значение, например 3, чтобы получилось
ID DATA FIN_PER
1 a 4:58.57,5:58.59
2 b 13:5.25,14:6.40
3 c 114:8.29,115:7.11,116:4.41
4 d 15:16.25

Ковырялся с substring,charindex,patindex но результата так и не добился, очень сложно.
Подскажите как это сделать? (Желательно без перебора каждой строки таблицы через курсор, потому что строк в таблице очень много)
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112902
Oleg_SQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
John__Smit,

string_split бы здесь был полезен...

Написать свою функцию или (гораздо лучше) поменять формат хранения в таблице на нормальный.

Код: sql
1.
2.
3.
4.
ID DATA  PERIOD BALANCE
1       a  1             58.57
2       a  2             58.59
...
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112904
Агрох
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
John__Smit
(грубо до 100 периодов)


Грубо говоря или точно до 100?

Рекурсией раскладываешь составные строки ("10:15.1, 15:44.44") на отдельные ("10:15.1" и "15:44.44").
С каждой отдельной строкой делаешь тёмное дело.
Склеиваешь их обратно в одну общую, по общему ID.
Апдейтишь таблицу новыми значениями.
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112911
John__Smit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Агрох

Грубо говоря или точно до 100?


До 100, до 200 не имеет значения, очень много. (В таблице 32 млн записей, я не проверял каждую)
(Апдейтить я буду тысяч 50 записей)

Агрох

Рекурсией раскладываешь составные строки ("10:15.1, 15:44.44") на отдельные ("10:15.1" и "15:44.44").
С каждой отдельной строкой делаешь тёмное дело.
Склеиваешь их обратно в одну общую, по общему ID.
Апдейтишь таблицу новыми значениями.


Это понятно. Можно чуть подробнее как в моей ситуации это сделать?
Сложность в том что у меня периоды могут задаваться разным числом знаков, я пытался писать скрипт по поиску от запятой до двоеточия, запутался. Наверняка есть красивый код который это делает.
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112913
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
John__Smit,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create table #t(id int, [data] varchar(20), FIN_PER varchar(50))

insert into #t select 1, 'a', '4:58.57,5:58.59'
insert into #t select 2, 'b', '13:5.25,14:6.40'
insert into #t select 3, 'c', '114:8.29,115:7.11,116:4.41'
insert into #t select 4, 'd', '15:16.25'

select id, data, FIN_PER, 
  CASE CHARINDEX(',', FIN_PER) 
    WHEN 0 THEN FIN_PER
	ELSE SUBSTRING(FIN_PER, 1, CHARINDEX(',', FIN_PER)-1) 
  END AS PartOne,
  CASE CHARINDEX(',', FIN_PER) 
    WHEN 0 THEN ''
	ELSE SUBSTRING(FIN_PER, CHARINDEX(',', FIN_PER)+1, (LEN(FIN_PER)-CHARINDEX(',', FIN_PER)))  
  END AS PartTwo
  from #t


drop table #t



Допилишь, используя еще CAST
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112915
Oleg_SQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
John__Smit,

32 млн записей...

А все же, зачем хранить данные в таком виде? Чтобы писать километры кода для ковыряния в нём?
Может проще 1 раз сесть и навести порядок?
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112932
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
John__Smit,

в колонке всегда должны находиться атомарные значение, то есть те, которые нельзя логически разбить на строки. Если у вас не так, то вам надо выполнить такое разделение, добавив дополнительные колонки и скорректировать п/о для заполнения и выборки.
Иначе ваша СУБД превращается в эксель.
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112940
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gerasimenko
John__Smit,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create table #t(id int, [data] varchar(20), FIN_PER varchar(50))

insert into #t select 1, 'a', '4:58.57,5:58.59'
insert into #t select 2, 'b', '13:5.25,14:6.40'
insert into #t select 3, 'c', '114:8.29,115:7.11,116:4.41'
insert into #t select 4, 'd', '15:16.25'

select id, data, FIN_PER, 
  CASE CHARINDEX(',', FIN_PER) 
    WHEN 0 THEN FIN_PER
	ELSE SUBSTRING(FIN_PER, 1, CHARINDEX(',', FIN_PER)-1) 
  END AS PartOne,
  CASE CHARINDEX(',', FIN_PER) 
    WHEN 0 THEN ''
	ELSE SUBSTRING(FIN_PER, CHARINDEX(',', FIN_PER)+1, (LEN(FIN_PER)-CHARINDEX(',', FIN_PER)))  
  END AS PartTwo
  from #t


drop table #t



Допилишь, используя еще CAST
не увидел, что переменное число.... Можно с помощью bulkinsert попробовать сначала разбить на столбцы
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112943
Агрох
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
WITH R0 AS (
SELECT 1 AS ID, '10:15.1,16:11.22,55:11.2' AS val
UNION
SELECT 2 AS ID, '1:55.55,2:26.05' AS val
UNION
SELECT 3 AS ID, '4:23.1' AS val
), R1 AS (
SELECT ID, 
  SUBSTRING(val, 1, CHARINDEX(':', val) - 1) AS val1, 
  CASE 
  	WHEN CHARINDEX(',', val) > 0 THEN SUBSTRING(val, CHARINDEX(':', val) + 1, CHARINDEX(',', val) - CHARINDEX(':', val) - 1)
  	ELSE SUBSTRING(val, CHARINDEX(':', val) + 1, len(val) - CHARINDEX(':', val))
  END AS val2, 
  CASE 
  	WHEN CHARINDEX(',', val) > 0 THEN SUBSTRING(val, CHARINDEX(',', val) + 1, len(val))
  	ELSE ''
  END as val
FROM R0
WHERE val <> ''
UNION all
SELECT ID, 
  SUBSTRING(val, 1, CHARINDEX(':', val) - 1) AS val1, 
  CASE 
  	WHEN CHARINDEX(',', val) > 0 THEN SUBSTRING(val, CHARINDEX(':', val) + 1, CHARINDEX(',', val) - CHARINDEX(':', val) - 1)
  	ELSE SUBSTRING(val, CHARINDEX(':', val) + 1, len(val) - CHARINDEX(':', val))
  END AS val2, 
  CASE 
  	WHEN CHARINDEX(',', val) > 0 THEN SUBSTRING(val, CHARINDEX(',', val) + 1, len(val))
  	ELSE ''
  END as val
FROM R1
WHERE val <> ''
), R2 AS (
SELECT
  ID,
  CAST(CAST(val1 AS int) + 5 AS VARCHAR(250)) AS val1,
  val2
FROM R1
)
SELECT * FROM R2 ORDER BY ID;



Объединять по моему через FOR XML PATH(''), но подзабыл уже как точно делать. Можно и через оконные попробовать или опять рекурсией.

P/S В "CAST(CAST(val1 AS int) + 5 AS VARCHAR(250)) AS val1," + 5 это то самое прибавление.
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40112976
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
declare @t table (id int, data varchar(20), FIN_PER varchar(50));

insert into @t select 1, 'a', '4:58.57,5:58.59';
insert into @t select 2, 'b', '13:5.25,14:6.40';
insert into @t select 3, 'c', '114:8.29,115:7.11,116:4.41';
insert into @t select 4, 'd', '15:16.25';

declare @x numeric(18,2) = 10;

select
 t.*, stuff(b.x.value('.', 'varchar(max)'), 1, 1, '')
from
 @t t cross apply
 (select cast('<item per = "' + replace(replace(t.FIN_PER, ':', '" rest = "'), ',', '"/><item per = "') + '"/>' as xml)) a(x) cross apply
 (
  select
   ',' + b.n.value('@per', 'varchar(10)') + ':' + cast(b.n.value('@rest', 'numeric(18,2)') + @x as varchar(30))
  from
   a.x.nodes('/item') b(n)
  for xml path(''), type
 ) b(x);
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40113021
John__Smit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Господа спасибо всем, но я лишь маленький винтик в системе. Понятно что структура хранения "г", но на неё заточено куча хранимых процедур. И даже если я предложу переделать её (и предположим даже нигде не накосячу), то большие дяди и тёти меня всё равно даже слушать не будут.

Уважаемый invm, ваш вариант почти идеален (хоть я пока и не понимаю как это работает), вот только прибавлять @x мне нужно к периоду а не к остаткам, и что то я пока не понимаю как это допилить
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40113051
John__Smit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Разобрался, допилил. Прочитал документацию по использованию методов nodes, value, предложения CROSS APPLY, вспомнил замечательную функцию stuff.

Уважаемый invm спасибо вам огромное, просто спасли меня (дай бог здоровья!). Постараюсь освоить данные методы в дальнейшем.
...
Рейтинг: 0 / 0
Поиск и обновление всех вхождений подстроки в строку
    #40113053
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
John__Smit
не понимаю как это допилить
Код: sql
1.
   ',' + cast(b.n.value('@per', 'int') + @x as varchar(10)) + ':' + b.n.value('@rest', 'varchar(30)')
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Поиск и обновление всех вхождений подстроки в строку
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]