Moh*_*hit 1 sql sql-server pivot unpivot sql-server-2012
我有一个表作为 MarketOutput 有 20 列
[Region] [LOB] [GWP 2013] [GWP 2014] [LR 2013] [LR 2014]
-------------------------------------------------------------
North Workers 38902.50 37,972,404 89 82
Run Code Online (Sandbox Code Playgroud)
我想将列动态更改为行。Region 和 LOB 是固定列,[GWP 2013], [GWP 2014], [LR 2013], [LR 2014] 是动态列。
明年他们将是[GWP 2015],[LR 2015]
我想取消旋转列并将 [GWP 2014] 拆分为两列 [GWP], [2014]。
输出应该是这样的
Region [LOB] [Metrics] [Year] [Value]
--------------------------------------------------
North Workers GWP 2013 38902.50
North Workers GWP 2014 37,972,404
North Workers LR 2013 89
North Workers LR 2014 82
Run Code Online (Sandbox Code Playgroud)
你能建议如何做到吗?
我是在 SQL Server 中进行透视的新手
我还想每次使用动态列表将输出插入到新表中
您只需要在执行以下操作后拆分列UNPIVOT:
WITH Unpivoted
AS
(
SELECT region, lob, columns, value
FROM Regions
UNPIVOT
(
columns
FOR value IN([GWP 2013] , [GWP 2014] ,
[LR 2013] , [LR 2014] ,
[GWP 2015], [LR 2015])
) AS u
)
SELECT
region,
lob,
columns,
CAST(CASE WHEN value LIKE 'GWP%' THEN REPLACE(value,'GWP ', '')
WHEN value LIKE 'LR%' THEN REPLACE(value,'LR ', '')
END AS INT) AS Year,
CASE WHEN value LIKE 'GWP%' THEN 'GWP'
WHEN value LIKE 'LR%' THEN 'LR'
END AS Metrics
FROM Unpivoted;
Run Code Online (Sandbox Code Playgroud)
然后当然你应该动态地做,以避免手动列出列并动态地做:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' +
QUOTENAME(column_name)
FROM information_schema.columns
WHERE table_name = 'Regions'
AND COLUMN_NAME <> 'Region'
AND COLUMN_NAME <> 'LOB'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT @query = 'WITH Unpivoted
AS
(
SELECT region, lob, columns, value
FROM Regions
UNPIVOT
(
columns
FOR value IN('+ @cols + ')
) AS u
)
SELECT
region,
lob,
columns,
CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
END AS INT) AS Year,
CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
WHEN value LIKE ''LR%'' THEN ''LR''
END AS Metrics
FROM Unpivoted';
EXECUTE(@query);
Run Code Online (Sandbox Code Playgroud)
假设以下情况,这应该可以正常工作:
[GWP 2013] , [GWP 2014] , [LR 2013] , [LR 2014] , [GWP 2015], [LR 2015], ... etc都采用相同的格式(GWP 或 LR,然后是空格,然后是年份,以及所有的列都是相同的数据类型int或十进制,如果数据类型不同,你应该在做之前unpivot将它们全部转换为一种数据类型,否则你会得到一个错误。
这会给你:
| region | lob | columns | Year | Metrics |
|--------|---------|----------|------|---------|
| North | Workers | 38902.5 | 2013 | GWP |
| North | Workers | 37972404 | 2014 | GWP |
| North | Workers | 70 | 2015 | GWP |
| North | Workers | 89 | 2013 | LR |
| North | Workers | 82 | 2014 | LR |
| North | Workers | 80 | 2015 | LR |
Run Code Online (Sandbox Code Playgroud)
我曾经FOR XML PATH('') ..将所有值列表连接到一个字符串中,这是 SQL Server 中的一种解决方法。的值@cols将是字符串:[GWP 2013], [GWP 2014], ...。
如果您的字段数据类型不同,您必须在执行以下操作之前对将在锚查询中取消透视的所有列进行强制转换UNPVOT:
SELECT @query = 'WITH Unpivoted
AS
(
SELECT region, lob, columns, value
FROM
(
SELECT
region,
lob,
CAST([GWP 2013] AS DECIMAL(10,2)) AS [GWP 2013],
CAST([GWP 2014] AS DECIMAL(10,2)) AS [GWP 2014],
... etc
FROM Regions
) AS t
UNPIVOT
(
columns
FOR value IN('+ @cols + ')
) AS u
)
SELECT
region,
lob,
columns,
CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
END AS INT) AS Year,
CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
WHEN value LIKE ''LR%'' THEN ''LR''
END AS Metrics
FROM Unpivoted';
Run Code Online (Sandbox Code Playgroud)
如果您发现手动为所有列编写演员表很困难,您可以动态生成并附加它,例如:
DECLARE @colsCasted AS NVARCHAR(MAX);
select @colsCasted = STUFF((SELECT distinct ',' +
'CAST(' + QUOTENAME(column_name) + 'AS DECIMAL(10,2)) AS ' + QUOTENAME(column_name)
FROM information_schema.columns
WHERE table_name = 'Regions'
AND COLUMN_NAME <> 'Region'
AND COLUMN_NAME <> 'LOB'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
Run Code Online (Sandbox Code Playgroud)
然后在动态查询中将该值附加到它:
SELECT @query = 'WITH Unpivoted
AS
(
SELECT region, lob, columns, value
FROM
(
SELECT region, lob,
' + @colsCasted + '
FROM Regions
) AS t
UNPIVOT
(
columns
FOR value IN('+ @cols + ')
) AS u
)
SELECT
region,
lob,
columns,
CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
END AS INT) AS Year,
CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
WHEN value LIKE ''LR%'' THEN ''LR''
END AS Metrics
FROM Unpivoted';
EXECUTE(@query);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6838 次 |
| 最近记录: |