连接两个表,然后将一个表中的行转置为列名 [英] Join Two Tables Then Transpose Rows From One Table As Column Names

查看:29
本文介绍了连接两个表,然后将一个表中的行转置为列名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试连接两个表

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            |linda@email.com      |Active  
3   |3            |Soft Eng.            |Active  
4   |4            |Cat 1                |Active
5   |1            |Remil                |Active
6   |2            |Remil@email.com      |Active  
7   |3            |Senior Soft Eng.     |Active  
8   |4            |Cat 2                |Active   
9   |1            |Ash                  |Active
10  |2            |ash@email.com        |Active  
11  |3            |Soft Eng.            |Active  
12  |4            |Cat 1                |Active  

然后将数据行(来自 ColumnNames 表上的 Name)转换为列名.

and then transposing rows of data (from Name on ColumnNames table) as column names.

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

Now, I was told to use Pivot. I've successfully used pivot for transposing rows from a single table, but I'm confused in how to transpose rows from joined tables.

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

Below is the code that I've tried, but it gives me an error saying columns doesn't exist

    @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     |linda@email.com       |Soft Eng.            |Cat 1
Remil     |Remil@email.com       |Senior Soft Eng.     |Cat 2
Ash       |ash@email.com         |Soft Eng.            |Cat 1

我在这种情况下是否正确使用了枢轴?

Am I utilizing pivot correctly on this scenario?

推荐答案

考虑在每个列值类型(全名、电子邮件、职位、类别)中使用 ROW_NUMBER 进行排名要包含在 INNER JOIN 中,然后通过 PIVOT 运行.无需动态构建 SQL:

Consider a ranking with ROW_NUMBER across each column value type (fullname, email, position, category) to be included in INNER JOIN then run through PIVOT. No need of dynamic building of 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 演示

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

For a dynamic query, build a @cols string to place in specific places of pivot query.

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 演示

这篇关于连接两个表,然后将一个表中的行转置为列名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆