Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто / 14 сообщений из 14, страница 1 из 1
18.09.2020, 12:38
    #40000225
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
SQL Server 2017 enterprise
Данные, приходящие из внешней системы имеют вид:

Код: sql
1.
2.
declare @names nvarchar(200) = 'Иван/Пётр/Алексей'
declare @families nvarchar(200) = 'Колесников/Дмитриев/Романин'


Необходимо получить таблицу:
Фамилия ИмяКолесников ИванДмитриев ПётрРоманин Алексей

Там в оригинале чуть сложнее:
Но в том виде, в каком сформулирован вопрос выше, решит мою проблему.

Из внешней системы приходит таблица:
Проект дата ... ... ... Ответственный (фамилия) Ответственный (имя) ...А ............ Колесников/Дмитриев/Романин Иван/Пётр/Алексей...Б ............ Колесников/Щеколдин Иван/Дмитрий...В ............ Щеколдин/Дмитриев/Романин Дмитрий/Пётр/Алексей...

Нужно разбить её на 3:
  • проекты ,
  • ответственные и
  • таблица многие-ко-многим .
И первый шаг - сформировать таблицу из ответственных.
Почему такая таблица через жопу? долго объяснять, но на внешнюю систему никак не повлиять.


Начал отталкиваться от решения:

Код: sql
1.
2.
select id = ROW_NUMBER() over( order by value ), t.value 
from string_split(R.Service, '/') t


Но невозможно сделать потом join по id, поскольку все значения перемешаны. А выделенную красным строку не убрать.

Для приведённого в предыдущем спойлере усложнения
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
select distinct fam, name
from Проекты
	cross apply (
		select fam,
			name
		from
			(
				select id = ROW_NUMBER() over( order by value ), fam = t.value --меняет порядок и рушит корректность соответствия имён фамилиям
				from string_split(R.family, '/') t
			) families
			join
			(
				select id = ROW_NUMBER() over( order by value ), [name]=t.value --меняет порядок и рушит корректность соответствия имён фамилиям
				from string_split(R.[Name], '/') t
			) names
			on families.id = names.id
	) t
order by family, name 

...
Рейтинг: 0 / 0
18.09.2020, 13:00
    #40000237
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Решения на основе string_split не гарантируют правильного результата, ибо https://docs.microsoft.com/ru-ru/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver15 Выходные строки могут быть расположены в любом порядке. Порядок не обязательно совпадает с порядком подстрок во входной строке.
Пишите собственную функцию парсинга строки, гарантирующую результирующий порядок подстрок.
Примеров реализации масса, в том числе и на этом форуме.
Из вчерашнего - 22199220
...
Рейтинг: 0 / 0
18.09.2020, 13:02
    #40000238
msLex
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
string_split не возвращает порядковый номер элемента.

Можно использовать альтернативный реализации string_split (CLR, UDF)
Можно вычислять порядок вот так


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
declare @names nvarchar(200) = 'Иван/Пётр/Алексей'



select 
	t.value
	, rn = row_number() over(order by  charindex('/' + t.value + '/', '/' + @names + '/'))
from string_split(@names, '/') t
...
Рейтинг: 0 / 0
18.09.2020, 13:19
    #40000241
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Charles Weyland
SQL Server 2017 enterprise
Данные, приходящие из внешней системы имеют вид

Каким образом данные приходят? Через линкед сервер, по почте, через API?
...
Рейтинг: 0 / 0
18.09.2020, 13:46
    #40000251
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Код: 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.
41.
42.
43.
44.
45.
46.
47.
48.
49.
declare @t table (project varchar, F varchar(max), N varchar(max))

insert into @t values
('А','Колесников/Дмитриев/Романин','Иван/Пётр/Алексей'),
('Б','Колесников/Щеколдин','Иван/Дмитрий'),
('В','Щеколдин/Дмитриев/Романин','Дмитрий/Пётр/Алексей')

-- select * from @t

;with cte as (
	select 
		t.*
		,a.xF
		,b.xN
		,cnt	=a.xF.value('count(/f)', 'int')
	from @t t
	cross apply(select cast('<f>'+replace(t.F,'/','</f><f>')+'</f>' as xml) as xF) a
	cross apply(select cast('<n>'+replace(t.N,'/','</n><n>')+'</n>' as xml) as xN) b
)
,q as (
	select
		cte.project
		,cte.xF
		,cte.xN
		,cte.xF.value('(f[1]/text())[1]','varchar(50)') as F
		,cte.xN.value('(n[1]/text())[1]','varchar(50)') as N
		,next_lvl	=2 
		,cnt
	from cte

	union all

	select
		q.project
		,q.xF
		,q.xN
		,q.xF.value('(f[sql:column("next_lvl")]/text())[1]','varchar(50)') 
		,q.xN.value('(n[sql:column("next_lvl")]/text())[1]','varchar(50)')
		,next_lvl + 1
		,cnt
	from q 
	where next_lvl <= cnt )

select 
	project
	,F
	,N 
from q
order by project, next_lvl



projectFNАКолесниковИванАДмитриевПётрАРоманинАлексейБКолесниковИванБЩеколдинДмитрийВЩеколдинДмитрийВДмитриевПётрВРоманинАлексей
...
Рейтинг: 0 / 0
18.09.2020, 13:51
    #40000254
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
msLex
Можно вычислять порядок вот так
будет проблема, если в списке есть тёзки
Код: sql
1.
2.
3.
4.
5.
6.
declare @names nvarchar(200) = 'Иван/Пётр/Алексей/Иван'

select 
	t.value
	, rn = row_number() over(order by  charindex('/' + t.value + '/', '/' + @names + '/'))
from string_split(@names, '/') t


valuernИван1Иван2Пётр3Алексей4
...
Рейтинг: 0 / 0
18.09.2020, 15:37
    #40000304
Ennor Tiegael
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
В 2017 можно через json:
Код: sql
1.
2.
3.
4.
5.
6.
declare @names nvarchar(200) = N'Иван/Пётр/Алексей',
	@families nvarchar(200) = N'Колесников/Дмитриев/Романин';

select *
from openjson('["' + replace(@names, '/', '","') + '"]') g
	full join openjson('["' + replace(@families, '/', '","') + '"]') f on f.[key] = g.[key];
...
Рейтинг: 0 / 0
20.09.2020, 06:06
    #40000608
Михаил Л
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Код: sql
1.
2.
declare @names nvarchar(200) = 'Иван/Пётр/Алексей'
declare @families nvarchar(200) = 'Колесников/Дмитриев/Романин'


Добрый день! Я извиняюсь. Когда выполняю этот код, получаю в ответ - "Выполнение команд успешно завершено. ", но ничего другого не вижу. Я так понимаю что где то создается таблица, может временная, но где ее посмотреть?
Очень плохо знаю sql.
...
Рейтинг: 0 / 0
21.09.2020, 02:58
    #40000719
PizzaPizza
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
declare создает переменную @names nvarchar(200) и задает её значение = 'Иван/Пётр/Алексей'
...
Рейтинг: 0 / 0
21.09.2020, 11:50
    #40000821
Агрох
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Волшебство рекурсий:
Код: 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.
WITH recursive R0 AS (
  SELECT 'a' As Pack, CAST('Иванов/Семёнов/Петров/Васечкин' AS VARCHAR(1000)) AS Fam, CAST('Семён/Иван/Семён/Фрол' AS VARCHAR(1000)) AS nam FROM RDB$DATABASE
  UNION ALL
  SELECT 'б' As Pack, CAST('Карпов/Кирин' AS VARCHAR(1000)) AS Fam, CAST('Иван/Иван/Семён' AS VARCHAR(1000)) AS nam FROM RDB$DATABASE
), R0_1 AS (
  SELECT Pack,
    CASE SUBSTRING(Fam FROM CHAR_LENGTH(Fam))
      WHEN '/' THEN Fam
      ELSE Fam||'/'
    end AS Fam,
    CASE SUBSTRING(nam FROM CHAR_LENGTH(nam))
      WHEN '/' THEN nam
      ELSE nam||'/'
    end AS nam
  FROM R0
), R1 AS (
  SELECT Pack,
    substring(Fam FROM 1 FOR position('/' in Fam) - 1) AS F,
    substring(Fam FROM position('/' in Fam) + 1) AS Fam,
    substring(nam FROM 1 FOR position('/' in nam) - 1) AS N,
    substring(nam FROM position('/' in nam) + 1) AS nam
  FROM R0_1

  UNION all

  SELECT Pack,
    substring(Fam FROM 1 FOR position('/' in Fam) - 1) AS F,
    substring(Fam FROM position('/' in Fam) + 1) AS Fam,
    substring(nam FROM 1 FOR position('/' in nam) - 1) AS N,
    substring(nam FROM position('/' in nam) + 1) AS nam
  FROM R1
  WHERE position('/' in Fam) > 0
    AND position('/' in nam) > 0
)
SELECT
  Pack,
  F,
  N
FROM R1;
...
Рейтинг: 0 / 0
21.09.2020, 11:57
    #40000826
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Модератор:
Агрох,

Уважаемый волшебник, а не хотите сначала научится не путать разделы форума?
...
Рейтинг: 0 / 0
21.09.2020, 12:14
    #40000836
Агрох
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Гавриленко Сергей Алексеевич
Модератор:
Агрох,

Уважаемый волшебник, а не хотите сначала научится не путать разделы форума?


Ок, учту.
...
Рейтинг: 0 / 0
22.09.2020, 13:59
    #40001290
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
Очень интересная ветка получилась.
спасибо!
...
Рейтинг: 0 / 0
23.09.2020, 19:30
    #40001869
Михаил Л
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто
PizzaPizza, спасибо!
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как строку xxx/yyy/zzz превратить в столбец и пронумеровать? непросто / 14 сообщений из 14, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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