SQL:动态视图,其列名基于源表中的列值

Dev*_*ate 5 sql sql-server sql-server-2005

鉴于这里有两个样本表:

门票表

ID  User    Description

0   James   This is a support ticket
1   Fred    This is a ticket too
Run Code Online (Sandbox Code Playgroud)

属性表

ID  TicketID    Label           Value

0   0           Engineer        Scott
1   1           Engineer        Dale
2   0           Manu            Dell
3   1           Manu            HP
4   0           OS              Windows
5   1           OS              Linux
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到这样的观点:

ID  User    Description                 Engineer    Manu    OS

1   James   This is a support ticket    Scott       Dell    Windows
2   Fred    This is a ticket too        Dale        HP      Linux
Run Code Online (Sandbox Code Playgroud)

值得注意的是,属性表并不总是相同.一些"门票"可能具有其他人没有的属性.

这甚至可能吗?

Tar*_*ryn 15

您可以使用PIVOT执行此操作.在执行PIVOT时,您可以使用以下两种方法之一:使用Static Pivot编写要转换的行,或使用Dynamic Pivot在运行时创建列列表:

Static Pivot(参见SQL小提琴演示):

select id, [user], [engineer], [manu], [OS]
from 
(
    select t.id
        , t.[user]
        , p.ticketid
        , p.label
        , p.value
    from tickets t
    inner join properties p
        on t.id = p.ticketid
) x
pivot
(
    min(value)
    for label in ([engineer], [manu], [OS])
) p
Run Code Online (Sandbox Code Playgroud)

或者您可以使用Dynamic Pivot(请参阅SQL Fiddle for Demo):

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(p.label) 
                    from tickets t
                    inner join properties p
                        on t.id = p.ticketid
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, [user], ' + @cols + ' from 
             (
                 select t.id
                        , t.[user]
                        , p.ticketid
                        , p.label
                        , p.value
                    from tickets t
                    inner join properties p
                        on t.id = p.ticketid
            ) x
            pivot 
            (
                min(value)
                for label in (' + @cols + ')
            ) p '

execute(@query)
Run Code Online (Sandbox Code Playgroud)

两个查询都将返回相同的结果.

  • @JeremyHolovacs 我不同意第一个比你的带有 3 个左连接的版本更复杂。就动态版本而言,OP 请求了一个灵活的动态版本的查询,这就是我提供的。总是有其他方法来回答问题,请随意提出另一种动态方法。:) (2认同)