Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Развернуть строку в столбец / 11 сообщений из 11, страница 1 из 1
04.11.2020, 13:57
    #40015198
S_A_V_e
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
Здравствуйте.

У меня есть система построения отчётов в которую можно передать sql запрос с параметром. Параметром может быть массив. И когда построитель отчёта видит в исходном запросе инструкцию IN(@ArrayParam1) в результирующем запросе он её подменяет на IN(@ArrayParam1_0,@ArrayParam1_1,...) создавая параметры для каждого элемента запроса.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
-- запрос отправляемый в построитель отчёта
select ID,[Name]
from MyTable
where
[Name] in(@ArrayParam1)

-- преобразуется в запрос
exec sp_executesql N'
select  ID,[Name]
from MyTable
where
[Name] in(@ArrayParam1_0, @ArrayParam1_1,...)',
N'@ArrayParam1_0 nvarchar(5), @ArrayParam1_0 nvarchar(5),...', @ArrayParam1_0 = N'1', @ArrayParam1_1 = N'2',....



Если же подставить @ArrayParam1 в select то будет сгенерирован select @ArrayParam1_0, @ArrayParam1_1,...

Вопрос:
Есть ли какой либо способ получить данные не в колонках, а в строках ? Т.е. как из select @ArrayParam1_0, @ArrayParam1_1,... получить таблицу с одной колонкой ? Количество колонок и их имена заранее не известны т.к. я не знаю сколько значений будет в исходном параметре @ArrayParam1.

Для примера:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
declare @a1 nvarchar(50) = N'1'
declare @a2 nvarchar(50) = N'2'
declare @a3 nvarchar(50) = N'3'

declare @result table([Value] nvarchar(5));

-- как из этого запроса записать данные всех колонок в таблицу @result
select @a1, @2, @a3
-- что бы вывести их в строках ?
select [Value] from @result



Помогите пожалуйста с запросом. Побороть своими силами не получилось.
...
Рейтинг: 0 / 0
04.11.2020, 14:48
    #40015215
Dimbuch®
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
S_A_V_e,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select @ArrayParam1_0
UNION ALL

select @ArrayParam1_1

UNION ALL

select @ArrayParam1_2

......
...
Рейтинг: 0 / 0
04.11.2020, 15:06
    #40015223
S_A_V_e
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
Нет. Такой вариант не подходит т.к. генератор просто подставляет строку вида @ArrayParam1_0, @ArrayParam1_1,... вместо исходного @ArrayParam1. Управлять этой генерацией и вставить что либо между @ArrayParam1_0 и @ArrayParam1_1 я не могу. Т.е. подставить это можно только в select и получить select @ArrayParam1_0, @ArrayParam1_1,... И вот из него нужно как то положить данные в табличку.
...
Рейтинг: 0 / 0
04.11.2020, 16:11
    #40015237
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
S_A_V_e
генератор просто подставляет строку вида @ArrayParam1_0, @ArrayParam1_1,... вместо исходного @ArrayParam1.
без именования полей вывода для этих элементов ?
т.е. так и остается
Код: sql
1.
select @ArrayParam1_0, @ArrayParam1_1


или, всё-таки, как-то так
Код: sql
1.
select @ArrayParam1_0 as col0, @ArrayParam1_1 as col1


?
...
Рейтинг: 0 / 0
04.11.2020, 16:22
    #40015239
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
S_A_V_e
У меня есть система построения отчётов в которую можно передать sql запрос с параметром. Параметром может быть массив. И когда построитель отчёта видит в исходном запросе инструкцию IN(@ArrayParam1) в результирующем запросе он её подменяет на IN(@ArrayParam1_0,@ArrayParam1_1,...) создавая параметры для каждого элемента запроса.
...
Если же подставить @ArrayParam1 в select то будет сгенерирован select @ArrayParam1_0, @ArrayParam1_1,...
А values(@ArrayParam1) он случайно не обрабатывает правильно?

Код: sql
1.
2.
3.
4.
exec sp_executesql N'
select  *
from (values(@ArrayParam1_0), (@ArrayParam1_1)) t(n)',
N'@ArrayParam1_0 nvarchar(5), @ArrayParam1_1 nvarchar(5)', @ArrayParam1_0 = N'1', @ArrayParam1_1 = N'2'
...
Рейтинг: 0 / 0
05.11.2020, 12:07
    #40015496
S_A_V_e
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
Не умеет с values работать. Получается во это:
Код: sql
1.
select * from (values(@ArrayParam1_0, @ArrayParam1_1, @ArrayParam1_2, @ArrayParam1_3, @ArrayParam1_4));
...
Рейтинг: 0 / 0
05.11.2020, 14:38
    #40015560
S_A_V_e
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
Костыль жуткий конечно, но работает. Может кому то пригодится.

Код: 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.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
-- внешние параметры определяемые построителем
declare @ArrayParam2_0 nvarchar(2),@ArrayParam2_1 nvarchar(2),@ArrayParam2_2 nvarchar(2),@ArrayParam2_3 nvarchar(2);
set @ArrayParam2_0=N'10' set @ArrayParam2_1=N'20' set @ArrayParam2_2=N'30'set  @ArrayParam2_3=N'40'; 

declare @Array2Values table ([Value] nvarchar(50)); -- таблица в которую нужно перегнать значения
declare @Array2Str nvarchar(max) = N'@ArrayParam2_0, @ArrayParam2_1, @ArrayParam2_2, @ArrayParam2_3'; -- так заходит строка из построителя отчёта в выпажение вида declare @Array2Str nvarchar(max) = N'@ArrayParam2'
                                                                                                      -- построитель подменяет выражение @ArrayParam2 даже внутри строк
declare @Array2Query nvarchar(max);
declare @Array2Prm nvarchar(max);

;with
 -- разбиваем строку по разделителю ',' и формируем строку запроса вида 'select arv.[Value] from ( values(@ArrayParam2_0),( @ArrayParam2_1),( @ArrayParam2_2),( @ArrayParam2_3) ) arv([Value])'
 strSrc as( select 
             FORMATMESSAGE('select arv.[Value] from ( values(%s)', SUBSTRING(@Array2Str, 0 , IIF(CHARINDEX(',', @Array2Str) = 0, LEN(@Array2Str) + 1, CHARINDEX(',', @Array2Str)))) as [Value],
			 SUBSTRING(@Array2Str, IIF(CHARINDEX(',', @Array2Str) = 0, LEN(@Array2Str) + 1, CHARINDEX(',', @Array2Str) + 1 ), LEN(@Array2Str)) as [Rest],
			 0 as Number			 
			 union all
			 select 
			 strSrc.[Value] + FORMATMESSAGE(',(%s)', SUBSTRING(strSrc.Rest, 0 , IIF(CHARINDEX(',', strSrc.Rest) = 0, LEN(strSrc.Rest) + 1, CHARINDEX(',', strSrc.Rest)))),
			 SUBSTRING(strSrc.Rest, IIF(CHARINDEX(',', strSrc.Rest) = 0, LEN(strSrc.Rest) + 1, CHARINDEX(',', strSrc.Rest) + 1 ), LEN(strSrc.Rest)),
			 strSrc.Number + 1			
			 from strSrc
			 where
			 strSrc.[Rest] <> '' 
			),
-- разбиваем строку по разделителю ',' и формируем строку с опрделением параметров вида '@ArrayParam2_0 nvarchar(50),  @ArrayParam2_1 nvarchar(50),  @ArrayParam2_2 nvarchar(50),  @ArrayParam2_3 nvarchar(50)'
strSrcPrm as( select 
              FORMATMESSAGE('%s nvarchar(50)', SUBSTRING(@Array2Str, 0 , IIF(CHARINDEX(',', @Array2Str) = 0, LEN(@Array2Str) + 1, CHARINDEX(',', @Array2Str)))) as [Value],
			  SUBSTRING(@Array2Str, IIF(CHARINDEX(',', @Array2Str) = 0, LEN(@Array2Str) + 1, CHARINDEX(',', @Array2Str) + 1 ), LEN(@Array2Str)) as [Rest],
			  0 as Number			 
			  union all
			  select 
			  strSrcPrm.[Value] + FORMATMESSAGE(', %s nvarchar(50)', SUBSTRING(strSrcPrm.Rest, 0 , IIF(CHARINDEX(',', strSrcPrm.Rest) = 0, LEN(strSrcPrm.Rest) + 1, CHARINDEX(',', strSrcPrm.Rest)))),
			  SUBSTRING(strSrcPrm.Rest, IIF(CHARINDEX(',', strSrcPrm.Rest) = 0, LEN(strSrcPrm.Rest) + 1, CHARINDEX(',', strSrcPrm.Rest) + 1 ), LEN(strSrcPrm.Rest)),
			  strSrcPrm.Number + 1			
			  from strSrcPrm
			  where
			  strSrcPrm.[Rest] <> '' 
			),
-- полная строка парамтетров в строке результата с наибольшим номером
queryPrm as ( select 
              top 1
              qp.[Value] as Params,
			  qp.Number
			  from 
			  strSrcPrm qp
			  order by qp.Number desc
			 ),
-- полная строка запроса в строке результата с наибольшим номером
queryStr as ( select 
              top 1
              FORMATMESSAGE('%s ) arv([Value])', q.[Value]) as Query,
			  q.Number
			  from 
			  strSrc q
			  order by q.Number desc
			 )
-- пишем запрос и параметры в переменные
select 
@Array2Query = q.Query,
@Array2Prm = p.Params  
from 
queryStr q 
inner join queryPrm p on q.Number = p.Number;



-- пишем в таблицу результат запроса
insert into @Array2Values
exec sp_executesql /*запрос*/@Array2Query, /*строка определения внутренних параметров запроса */@Array2Prm, /*значения из внешних парамтеров*/@ArrayParam2_0 ,@ArrayParam2_1 ,@ArrayParam2_2 ,@ArrayParam2_3;

select * from @Array2Values;



Спасибо всем кто поучаствовал. Вопрос в целом решен. Если знаете как сделать то же самое проще - напишите пожалуйста.
...
Рейтинг: 0 / 0
05.11.2020, 16:43
    #40015606
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
S_A_V_e,

пригодиться может лишь тому, у кого ваша оригинальная "система построения отчётов".
...
Рейтинг: 0 / 0
06.11.2020, 09:06
    #40015843
S_A_V_e
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
Telerik.Reporting. Я точно не единственный кто её использует.
...
Рейтинг: 0 / 0
06.11.2020, 10:54
    #40015872
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
S_A_V_e
Если знаете как сделать то же самое проще - напишите пожалуйста.

раз уж дело дошло до парсинга, то все эти "приседания" с рекурсией точно не нужны
replace-а достаточно :)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
-- внешние параметры определяемые построителем
declare @ArrayParam2_0 nvarchar(2),@ArrayParam2_1 nvarchar(2),@ArrayParam2_2 nvarchar(2),@ArrayParam2_3 nvarchar(2);
set @ArrayParam2_0=N'10' set @ArrayParam2_1=N'20' set @ArrayParam2_2=N'30'set  @ArrayParam2_3=N'40'; 

declare @Array2Values table ([Value] nvarchar(50)); -- таблица в которую нужно перегнать значения
declare @Array2Str nvarchar(max) = N'@ArrayParam2_0, @ArrayParam2_1, @ArrayParam2_2, @ArrayParam2_3'; -- так заходит строка из построителя отчёта в выпажение вида declare @Array2Str nvarchar(max) = N'@ArrayParam2'
                                                                                                      -- построитель подменяет выражение @ArrayParam2 даже внутри строк
declare @Array2Query nvarchar(max);
declare @Array2Prm nvarchar(max);

--	***********************************************************************

set @Array2Query = 'select arv.[Value] from ( values(' + replace(@Array2Str, ',', '),(') + ')) arv([Value])';
set @Array2Prm = replace(@Array2Str, ',', ' nvarchar(50),') + ' nvarchar(50)';

print @Array2Query
print @Array2Prm

-- пишем в таблицу результат запроса
insert into @Array2Values
exec sp_executesql /*запрос*/@Array2Query, /*строка определения внутренних параметров запроса */@Array2Prm, /*значения из внешних парамтеров*/@ArrayParam2_0 ,@ArrayParam2_1 ,@ArrayParam2_2 ,@ArrayParam2_3;

select * from @Array2Values;
...
Рейтинг: 0 / 0
06.11.2020, 16:12
    #40016005
S_A_V_e
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Развернуть строку в столбец
Вот спасибо большое ! Так намного лучше. Я не додумался replace по запятой сделать.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Развернуть строку в столбец / 11 сообщений из 11, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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