加入两个表,然后将一个表中的行转置为列名

问题描述 投票:1回答:1

我正在尝试合并两个表

ColumnNames
ID  |Name        |Type    |Status |
-----------------------------------------------------
1   |Fullname    |varchar |Active
2   |Email       |varchar |Active  
3   |Position    |varchar |Active  
4   |Category    |varchar |Active
ColumnValues
ID  |ColumnNameID |value                |Status |
-----------------------------------------------------
1   |1            |Linda                |Active
2   |2            |[email protected]      |Active  
3   |3            |Soft Eng.            |Active  
4   |4            |Cat 1                |Active
5   |1            |Remil                |Active
6   |2            |[email protected]      |Active  
7   |3            |Senior Soft Eng.     |Active  
8   |4            |Cat 2                |Active   
9   |1            |Ash                  |Active
10  |2            |[email protected]        |Active  
11  |3            |Soft Eng.            |Active  
12  |4            |Cat 1                |Active  

,然后将数据行(从ColumnNames表上的Name转换为列名)。

现在,有人告诉我要使用Pivot。我已经成功地使用数据透视表来转置单个表中的行,但是我对如何转置联接表中的行感到困惑。

下面是我尝试过的代码,但是它给我一个错误,指出不存在列

    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(ColumnName) 
                    from tm.ColumnName
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT ColumnNameID, ' + @cols + ' from 
             (
                select i.ColumnNameID, i.ColumnValue
                from tm.ColumnValue i
                inner join tm.ColumnName a
                  on i.ColumnNameID = a.ColumnNameID
            ) x
            pivot 
            (
                max(ColumnNameID)
                for ColumnValue in (' + @cols + ')
            ) p '

execute(@query)

预期结果应该是

Fullname  |Email                 |Position             |Category |
--------------------------------------------------------------------
Linda     |[email protected]       |Soft Eng.            |Cat 1
Remil     |[email protected]       |Senior Soft Eng.     |Cat 2
Ash       |[email protected]         |Soft Eng.            |Cat 1

我在这种情况下可以正确利用数据透视吗?

sql sql-server sql-server-2014
1个回答
0
投票

考虑要包含在ROW_NUMBER中的每种列值类型(全名,电子邮件,职位,类别上的INNER JOIN的等级,然后遍历PIVOT)。无需动态构建SQL:

SELECT [Fullname], [Email], [Position], [Category]
FROM (
    SELECT i.ColumnValue, a.[Name],
           ROW_NUMBER() OVER (PARTITION BY a.[Name] ORDER BY a.ColumnNameID) AS rn
    FROM ColumnValues i
    INNER JOIN ColumnNames a
      ON i.ColumnNameID = a.ColumnNameID
  ) tbl

PIVOT
   (MAX(ColumnValue) 
    FOR [Name] IN ([Fullname], [Email], [Position], [Category])
   ) pvt
ORDER BY rn

Rextester demo

对于动态查询,构建一个@cols字符串以放置在数据透视查询的特定位置。

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[Name]) 
            FROM ColumnNames c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
             ,1,1,'')

SET @query = 'SELECT ' + @cols + '
                FROM (
                    SELECT i.ColumnValue, a.[Name],
                           ROW_NUMBER() OVER (PARTITION BY a.[Name] ORDER BY a.ColumnNameID) AS rn
                    FROM ColumnValues i
                    INNER JOIN ColumnNames a
                      ON i.ColumnNameID = a.ColumnNameID
                  ) tbl

                PIVOT
                   (MAX(ColumnValue) 
                    FOR [Name] IN (' + @cols + ')
                   ) pvt
                ORDER BY rn'

EXECUTE(@query)

Rextester demo

© www.soinside.com 2019 - 2024. All rights reserved.