Sql server 使用多组列的SQL Server Pivot

Sql server 使用多组列的SQL Server Pivot,sql-server,pivot,unpivot,Sql Server,Pivot,Unpivot,从这样的表格中: 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

从这样的表格中:

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个组件):

我已经查看并尝试修改了这里介绍的一系列pivot和unpivot解决方案,包括动态和静态列定义,但没有一个解决方案看起来最有可能工作,因此我不知道建议哪些解决方案可以用于解决方案

我非常希望能就哪种程序/机制最适合这一点提供一些指导


提前感谢。

解决此问题的一个简单方法是编写如下查询

;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)
返回


这需要使用动态查询来完成,因为即使使用技巧,数据透视仍然不支持动态列数。下面是一个创建表的动态SQL示例。我把它留给你

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

向上投票获取样本数据,以文本形式发布预期结果有助于那些处于图像被屏蔽领域的人们。我采用这种方法,因为:a)这是可以理解的,并且很容易包含在更复杂的场景中;b) 它可以一次完成整个查询;c) 它在一个大的数据库上表现得非常好;d) 它可以合并到视图中,因此更有用。非常感谢你的帮助。谢谢,欢迎。是的,我做了一个执行计划比较,发现这种方法更好。我还发现约翰的方法很有趣。。所以只有我支持他的方法。。。
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