powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Динамический Unpivot с несколькими столбцами
4 сообщений из 4, страница 1 из 1
Динамический Unpivot с несколькими столбцами
    #39900857
Yaroslav85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет.
На просторах интернета нашел интересную процедуру для динамического Unpivot:
тут:
https://bengribaudo.com/blog/2015/02/05/3383/dynamic-unpivot-stored-procedure
Код: 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.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
CREATE TYPE ColumnList AS TABLE
(                     
    name SYSNAME NOT NULL PRIMARY KEY
)
GO
 
-- Provided "as is" with no warranties of any kind. User assumes all risks of use.
CREATE PROCEDURE DynamicUnpivot
    @Query NVARCHAR(MAX),                   -- Query producing the resultset to unpivot.
    @Column SYSNAME = NULL,                 -- Name of single column. Combined with @ColumnList to control which columns are unpivoted.
    @ColumnList ColumnList READONLY,        -- List of column names. Combined with @Column to control which columns are unpivoted.
    @UnpivotSpecified BIT = 0,              -- Indicates whether the specified columns (@UnpivotSpecified = 1) or all other columns execpt 
                                            --  the specified (@UnpivotSpecified = 0) should be unpivoted.
    @ValueColumnName SYSNAME = 'Value',     -- Name of value-containing column in the output resultset.
    @ColumnColumnName SYSNAME = 'Column',   -- Name of column-name-containing column in the output resultset.
    @ValueColumnType NVARCHAR(20) = 'NVARCHAR(100)',    -- Data type of output value column. All source columns that are unpivoted are CAST to this data type.
    @OnlyOutputSql BIT = 0                  -- Controls whether the unpivot query is executed and its resultset returned (@OnlyOutputSql = 0) 
                                            --  or not executed and its SQL outputted (@OnlyOutputSql = 1).
AS
BEGIN
SET NOCOUNT ON;
 
 
/*
    Combine both column name inputs into one table variable. 
    UNIONing protects from duplicates when @Column is also in @ColumnList
*/
DECLARE @Columns dbo.ColumnList
 
INSERT INTO @Columns
SELECT name FROM @ColumnList
UNION
SELECT @Column WHERE @Column IS NOT NULL
 
 
/*
    Build a list of all columns to be returned, indicating which should be unpivoted.
 
    If @UnpivotSpecified = 1, column names found in *both* the input column names and the
    query's result set will be unpivoted. All other columns in the result set will be 
    output without unpivoting. 
     
    @UnpivotSpecified = 0 inverts this behavior.
*/
DECLARE @QueryColumns TABLE (
    name sysname NOT NULL PRIMARY KEY, 
    column_ordinal INT NOT NULL,
    ShouldUnpivot BIT NOT NULL
);
 
INSERT @QueryColumns
SELECT
    r.name, 
    column_ordinal, 
    ShouldUnpivot = CASE WHEN @UnpivotSpecified = 1 THEN
        CASE WHEN c.name IS NOT NULL THEN 1 ELSE 0 END
    ELSE
        CASE WHEN c.name IS NOT NULL THEN 0 ELSE 1 END
    END
FROM sys.dm_exec_describe_first_result_set(@Query, NULL, 0) r
    LEFT JOIN @Columns c ON r.name = c.name
WHERE is_hidden = 0
    AND r.name IS NOT NULL
    AND column_ordinal IS NOT NULL
 
 
DECLARE @ColumnName SYSNAME,
    @First BIT = 1
 
/*
    Assemble cast & unpivot SQL.
*/
DECLARE @CastSql NVARCHAR(MAX) = '',
    @UnpivotSql NVARCHAR(MAX) = ''
 
 
DECLARE upvt CURSOR FAST_FORWARD FOR 
    SELECT name FROM @QueryColumns WHERE ShouldUnpivot = 1 ORDER BY column_ordinal
 
OPEN upvt
 
FETCH NEXT FROM upvt 
    INTO @ColumnName;
 
WHILE @@FETCH_STATUS = 0 BEGIN
    IF @First = 0 
    BEGIN
        SET @CastSql += ', '
        SET @UnpivotSql += ', '
    END
 
    SET @CastSql += QUOTENAME(@ColumnName) + ' = CAST(' + QUOTENAME(@ColumnName) + ' AS ' + @ValueColumnType + ')'
    SET @UnpivotSql += QUOTENAME(@ColumnName)
 
    IF @First = 1
        SET @First = 0
 
    FETCH NEXT FROM upvt
        INTO @ColumnName
END
 
CLOSE upvt
DEALLOCATE upvt
 
 
/*
    Assemble SQL for non-unpivoted columns.
*/
DECLARE @NoUnpivotSql NVARCHAR(MAX) = ''
SET @First = 1
 
DECLARE npvt CURSOR FAST_FORWARD FOR 
    SELECT name FROM @QueryColumns WHERE ShouldUnpivot = 0 ORDER BY column_ordinal
 
OPEN npvt
 
FETCH NEXT FROM npvt
    INTO @ColumnName
 
WHILE @@FETCH_STATUS = 0 BEGIN
    IF @First = 0 
        SET @NoUnpivotSql += ', '
         
    SET @NoUnpivotSql += QUOTENAME(@ColumnName)
 
    IF @First = 1
        SET @First = 0
 
    FETCH NEXT FROM npvt
        INTO @ColumnName
END;
 
CLOSE npvt
DEALLOCATE npvt
 
 
/*
    Build the final query.
*/
DECLARE @NewLine NVARCHAR(2) = CHAR(13) + CHAR(10),
    @Tab NVARCHAR(1) = CHAR(9)
DECLARE @OutputSql NVARCHAR(max) = 'SELECT *
FROM (
    SELECT
        ' + @NoUnpivotSql + ', 
        ' + @CastSql + '
    FROM (
        ' + @Query + '
        ) innerData
) data
    UNPIVOT (' + QUOTENAME(@ValueColumnName) + ' FOR ' + QUOTENAME(@ColumnColumnName) + ' IN (' + @UnpivotSql + ')) upvt'
 
/*
    Produce output.
*/
SET NOCOUNT OFF
 
IF @OnlyOutputSql = 0
    EXEC sp_executesql @OutputSql
ELSE
    PRINT @OutputSql
 
END
GO



темповая тестовая таблица:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
If(OBJECT_ID('tempdb..#TempT2') Is Not Null)
Begin  Drop Table #TempT2 End
SELECT * into #TempT2
 FROM (VALUES
	 (N'т1',N'col2_1',N'col3_1',6,6,3,2,6,5,8)
	,(N'т2',N'col2_2',N'col3_2',0,0,0,0,0,0,0)
	,(N'т3',N'col2_3',N'col3_3',0,0,0,0,0,0,0)
	,(N'т4',N'col2_4',N'col3_4',14,13,8,5,14,16,12)
	,(N'т5',N'col2_5',N'col3_5',4,4,2,1,5,3,4)
	,(N'т6',N'col2_6',N'col3_6',0,1,1,1,1,2,1)
	,(N'т7',N'col2_7',N'col3_7',5,4,4,2,3,5,4)
) as x([col1],[col2],[col3],[col4],[col5],[col6],[col7],[col8],[col9],[col10])
Select * from #TempT2


с одним столбцом во втором параметре работает

Код: sql
1.
2.
3.
EXEC DynamicUnpivot
		N'SELECT * from  #TempT2'
		,@Column = N'col1'



Внимание вопрос:
как передать в третий параметр название еще нескольких столбцов?
Код: sql
1.
2.
3.
4.
	EXEC DynamicUnpivot
		N'SELECT * from  #TempT2'
		,@Column = N'col1'
		,@ColumnList = 'col2,col3'/*вот сюда как передать параметр?*/
...
Рейтинг: 0 / 0
Динамический Unpivot с несколькими столбцами
    #39900871
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yaroslav85, это табличная переменная:

Код: sql
1.
    @ColumnList ColumnList READONLY,        -- List of column names. Combined with @Column to control which columns are unpivoted.



Объявляете табличную переменную, заполняете значениями, передаете в процедуру.
...
Рейтинг: 0 / 0
Динамический Unpivot с несколькими столбцами
    #39900888
Yaroslav85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Minamoto

Объявляете табличную переменную, заполняете значениями, передаете в процедуру.

а можете пример кинуть?
я пробовал и так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
declare @T as table (name SYSNAME)
insert into @T select 'col2'
insert into @T select 'col3'
select * from @T
	EXEC DynamicUnpivot
		N'SELECT * from  #TempT2'
		,@Column = N'col1'
		,@ColumnList =  @T/*вот сюда как передать?*/



дает ошибку:
Msg 206, Level 16, State 2, Procedure DynamicUnpivot, Line 0 [Batch Start Line 21]
Operand type clash: table is incompatible with ColumnList
...
Рейтинг: 0 / 0
Динамический Unpivot с несколькими столбцами
    #39900889
Yaroslav85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Minamoto,

спасибо . Погуглил ошибку - дошло :)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
DECLARE @T AS ColumnList 
insert into @T select 'col2'
insert into @T select 'col3'
select * from @T

	EXEC DynamicUnpivot
		N'SELECT * from  #TempT2'
		,@Column = N'col1'
		,@ColumnList =  @T/*вот сюда как передать?*/


работает :)
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Динамический Unpivot с несколькими столбцами
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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