SQL Server Pivot 使用多组列
SQL Server Pivot using multiple sets of columns
来自 table 这样的:
CREATE TABLE dbo.mytable
(
[ID] int,
[Category] INT,
[Lh] varchar(30),
[Sev] INT,
[Risk] INT
)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (5, 2, 'Impossible', 4, 10)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 2, 'Unlikely', 3, 13)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 3, 'Possible', 3, 18)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 5, 'Likely', 3, 23)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 6, 'Possible', 3, 18)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (7, 2, 'Impossible', 5, 15)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (8, 2, 'Very Unlikely', 5, 20)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (9, 2, 'Unlikely', 6, 30)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 2, 'Impossible', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 6, 'Impossible', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 1, 'Impossible', 4, 10)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 2, 'Very Unlikely', 5, 20)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 4, 'Impossible', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (13, 2, 'Impossible', 6, 21)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (14, 2, 'Impossible', 6, 21)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 1, 'Very Unlikely', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 2, 'Impossible', 5, 15)
我正在尝试创建一个如下所示的结果集(请记住,可能有任意数量的类别,但每个类别始终有 3 个组件):
ID Cat_1_Lh Cat_1_Sev Cat_1_Risk Cat_2_Lh Cat_2_Sev Cat_2_Risk Cat_3_Lh Cat_3_Sev Cat_3_Risk Cat_4_Lh Cat_4_Sev Cat_4_Risk Cat_5_Lh Cat_5_Sev Cat_5_Risk Cat_6_Lh Cat_6_Sev Cat_6_Risk
5 Impossible 4 10
6 Unlikely 3 13 Possible 3 18 Likely 3 23 Possible 3 18
7 Impossible 5 15
8 Very Unlikely 5 20
9 Unlikely 6 30
10 Impossible 3 6 Impossible 3 6
12 Impossible 4 10 Very Unlikely 5 20 Impossible 3 6
13 Impossible 6 21
14 Impossible 6 21
15 Very Unlikely 3 6 Impossible 5 15
我已经查看并尝试修改此处提供的一系列枢轴和反枢轴解决方案,包括动态和静态列定义,但 none 看起来它们的工作机会微乎其微,所以我不不知道可以将哪些建议用于解决方案。
对于 process/mechanism 最适合的一些指导,我将不胜感激。
提前致谢。
解决这个问题的一种天真的方法是像这样编写查询
;with cte_lh as (
select Id, max([1]) as Cat_1_lh,max([2]) as Cat_2_lh,max([3]) as Cat_3_lh,max([4]) as Cat_4_lh,max([5]) as Cat_5_lh,max([6]) as Cat_6_lh from mytable
pivot(max(Lh) for Category in ([1],[2],[3],[4],[5],[6])) as p
group by id
), cte_sev as (
select id, max([1]) as Cat_1_Sev,max([2]) Cat_2_Sev,max([3]) Cat_3_Sev,max([4]) Cat_4_Sev,max([5]) Cat_5_Sev,max([6]) Cat_6_Sev from mytable
pivot (max(sev) for category in ([1],[2],[3],[4],[5],[6])) as p
group by id
), cte_risk as (
select id, max([1]) Cat_1_Risk,max([2]) Cat_2_Risk,max([3]) Cat_3_Risk,max([4]) Cat_4_Risk,max([5]) Cat_5_Risk,max([6]) Cat_6_Risk from mytable
pivot (max(risk) for category in ([1],[2],[3],[4],[5],[6])) as p
group by id
) select * from cte_lh lh join cte_sev sev on lh.id = sev.id
join cte_risk risk on lh.id = risk.id
我们可以在动态 sql 中创建列,如果您的列列表不同,我们可以添加列并创建动态 sql..
如果你不介意动态化
Declare @SQL varchar(max) = ''
Declare @BaseCols varchar(max) ='
,Cat_#_Lh = max(case when Category=# then LH else '''' end)
,Cat_#_Sev = max(case when Category=# then cast(Sev as varchar(25)) else '''' end)
,Cat_#_Risk = max(case when Category=# then cast(Risk as varchar(25)) else '''' end)
'
Select @SQL = @SQL + Replace(@BaseCols,'#',Category) from (Select Distinct Category from myTable) A
Set @SQL = 'Select ID'+@SQL + ' From myTable Group By ID Order by ID'
Exec(@SQL)
Returns
这将需要通过动态查询来完成,因为即使使用技巧,旋转仍然不支持动态列数。下面是动态 SQL 创建 table 的示例。我把它留给你。
DECLARE @stmt nvarchar(max) = '
DECLARE @tbl TABLE
(
'
DECLARE @mytable TABLE
(
[ID] int,
[Category] INT,
[Lh] varchar(30),
[Sev] INT,
[Risk] INT
)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (5, 2, 'Impossible', 4, 10)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 2, 'Unlikely', 3, 13)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 3, 'Possible', 3, 18)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 5, 'Likely', 3, 23)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 6, 'Possible', 3, 18)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (7, 2, 'Impossible', 5, 15)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (8, 2, 'Very Unlikely', 5, 20)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (9, 2, 'Unlikely', 6, 30)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 2, 'Impossible', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 6, 'Impossible', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 1, 'Impossible', 4, 10)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 2, 'Very Unlikely', 5, 20)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 4, 'Impossible', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (13, 2, 'Impossible', 6, 21)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (14, 2, 'Impossible', 6, 21)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 1, 'Very Unlikely', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 2, 'Impossible', 5, 15)
DECLARE @categories TABLE
(
[Category] INT
)
INSERT @categories SELECT DISTINCT [Category] FROM @mytable ORDER BY [Category]
WHILE ((SELECT TOP 1 [Category] FROM @categories ORDER BY [Category]) IS NOT NULL)
BEGIN
DECLARE @category int = (SELECT TOP 1 [Category] FROM @categories ORDER BY [Category])
SET @stmt = @stmt + '[Cat_' + CAST(@category AS VARCHAR(max)) + '_Lh] VARCHAR(MAX)
,[Cat_' + CAST(@category AS VARCHAR(max)) + '_Sev] INT
,[Cat_' + CAST(@category AS VARCHAR(max)) + '_Risk] INT
' + CASE
WHEN (SELECT count(*) FROM @categories) > 1 THEN ' ,'
ELSE ')'
END
DELETE TOP (1) FROM @categories
END
SET @stmt = @stmt + '
SELECT * FROM @tbl [tbl]'
EXEC sp_executesql @stmt
来自 table 这样的:
CREATE TABLE dbo.mytable
(
[ID] int,
[Category] INT,
[Lh] varchar(30),
[Sev] INT,
[Risk] INT
)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (5, 2, 'Impossible', 4, 10)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 2, 'Unlikely', 3, 13)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 3, 'Possible', 3, 18)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 5, 'Likely', 3, 23)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 6, 'Possible', 3, 18)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (7, 2, 'Impossible', 5, 15)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (8, 2, 'Very Unlikely', 5, 20)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (9, 2, 'Unlikely', 6, 30)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 2, 'Impossible', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 6, 'Impossible', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 1, 'Impossible', 4, 10)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 2, 'Very Unlikely', 5, 20)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 4, 'Impossible', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (13, 2, 'Impossible', 6, 21)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (14, 2, 'Impossible', 6, 21)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 1, 'Very Unlikely', 3, 6)
insert into mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 2, 'Impossible', 5, 15)
我正在尝试创建一个如下所示的结果集(请记住,可能有任意数量的类别,但每个类别始终有 3 个组件):
ID Cat_1_Lh Cat_1_Sev Cat_1_Risk Cat_2_Lh Cat_2_Sev Cat_2_Risk Cat_3_Lh Cat_3_Sev Cat_3_Risk Cat_4_Lh Cat_4_Sev Cat_4_Risk Cat_5_Lh Cat_5_Sev Cat_5_Risk Cat_6_Lh Cat_6_Sev Cat_6_Risk
5 Impossible 4 10
6 Unlikely 3 13 Possible 3 18 Likely 3 23 Possible 3 18
7 Impossible 5 15
8 Very Unlikely 5 20
9 Unlikely 6 30
10 Impossible 3 6 Impossible 3 6
12 Impossible 4 10 Very Unlikely 5 20 Impossible 3 6
13 Impossible 6 21
14 Impossible 6 21
15 Very Unlikely 3 6 Impossible 5 15
我已经查看并尝试修改此处提供的一系列枢轴和反枢轴解决方案,包括动态和静态列定义,但 none 看起来它们的工作机会微乎其微,所以我不不知道可以将哪些建议用于解决方案。
对于 process/mechanism 最适合的一些指导,我将不胜感激。
提前致谢。
解决这个问题的一种天真的方法是像这样编写查询
;with cte_lh as (
select Id, max([1]) as Cat_1_lh,max([2]) as Cat_2_lh,max([3]) as Cat_3_lh,max([4]) as Cat_4_lh,max([5]) as Cat_5_lh,max([6]) as Cat_6_lh from mytable
pivot(max(Lh) for Category in ([1],[2],[3],[4],[5],[6])) as p
group by id
), cte_sev as (
select id, max([1]) as Cat_1_Sev,max([2]) Cat_2_Sev,max([3]) Cat_3_Sev,max([4]) Cat_4_Sev,max([5]) Cat_5_Sev,max([6]) Cat_6_Sev from mytable
pivot (max(sev) for category in ([1],[2],[3],[4],[5],[6])) as p
group by id
), cte_risk as (
select id, max([1]) Cat_1_Risk,max([2]) Cat_2_Risk,max([3]) Cat_3_Risk,max([4]) Cat_4_Risk,max([5]) Cat_5_Risk,max([6]) Cat_6_Risk from mytable
pivot (max(risk) for category in ([1],[2],[3],[4],[5],[6])) as p
group by id
) select * from cte_lh lh join cte_sev sev on lh.id = sev.id
join cte_risk risk on lh.id = risk.id
我们可以在动态 sql 中创建列,如果您的列列表不同,我们可以添加列并创建动态 sql..
如果你不介意动态化
Declare @SQL varchar(max) = ''
Declare @BaseCols varchar(max) ='
,Cat_#_Lh = max(case when Category=# then LH else '''' end)
,Cat_#_Sev = max(case when Category=# then cast(Sev as varchar(25)) else '''' end)
,Cat_#_Risk = max(case when Category=# then cast(Risk as varchar(25)) else '''' end)
'
Select @SQL = @SQL + Replace(@BaseCols,'#',Category) from (Select Distinct Category from myTable) A
Set @SQL = 'Select ID'+@SQL + ' From myTable Group By ID Order by ID'
Exec(@SQL)
Returns
这将需要通过动态查询来完成,因为即使使用技巧,旋转仍然不支持动态列数。下面是动态 SQL 创建 table 的示例。我把它留给你。
DECLARE @stmt nvarchar(max) = '
DECLARE @tbl TABLE
(
'
DECLARE @mytable TABLE
(
[ID] int,
[Category] INT,
[Lh] varchar(30),
[Sev] INT,
[Risk] INT
)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (5, 2, 'Impossible', 4, 10)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 2, 'Unlikely', 3, 13)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 3, 'Possible', 3, 18)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 5, 'Likely', 3, 23)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (6, 6, 'Possible', 3, 18)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (7, 2, 'Impossible', 5, 15)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (8, 2, 'Very Unlikely', 5, 20)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (9, 2, 'Unlikely', 6, 30)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 2, 'Impossible', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (10, 6, 'Impossible', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 1, 'Impossible', 4, 10)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 2, 'Very Unlikely', 5, 20)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (12, 4, 'Impossible', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (13, 2, 'Impossible', 6, 21)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (14, 2, 'Impossible', 6, 21)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 1, 'Very Unlikely', 3, 6)
insert into @mytable ([ID], [Category], [Lh], [Sev], [Risk]) values (15, 2, 'Impossible', 5, 15)
DECLARE @categories TABLE
(
[Category] INT
)
INSERT @categories SELECT DISTINCT [Category] FROM @mytable ORDER BY [Category]
WHILE ((SELECT TOP 1 [Category] FROM @categories ORDER BY [Category]) IS NOT NULL)
BEGIN
DECLARE @category int = (SELECT TOP 1 [Category] FROM @categories ORDER BY [Category])
SET @stmt = @stmt + '[Cat_' + CAST(@category AS VARCHAR(max)) + '_Lh] VARCHAR(MAX)
,[Cat_' + CAST(@category AS VARCHAR(max)) + '_Sev] INT
,[Cat_' + CAST(@category AS VARCHAR(max)) + '_Risk] INT
' + CASE
WHEN (SELECT count(*) FROM @categories) > 1 THEN ' ,'
ELSE ')'
END
DELETE TOP (1) FROM @categories
END
SET @stmt = @stmt + '
SELECT * FROM @tbl [tbl]'
EXEC sp_executesql @stmt