SQL Server从表中获取行并显示在列中

时间:2017-06-20 11:35:36

标签: sql sql-server

我是SQL的初学者并且有一个问题。我有一个包含这样的用户数据的表

uid  nid val   
+---+---+---+
| 1 | x | 3 |
+---+---+---+
| 2 | x | 3 |
+---+---+---+
| 3 | x | 3 |
+---+---+---+
| 1 | y | 4 |
+---+---+---+
| 2 | y | 4 |
+---+---+---+
| 3 | y | 4 |
+---+---+---+
| 1 | z | 5 |
+---+---+---+

其中uid是用户ID,nid是名称id,用于标识值,val是实际值。

我想写一个查询,它给出了以下结果

uid   x   y   z
+---+---+---+---+
| 1 | 3 | 4 | 5 |
+---+---+---+---+
| 2 | 3 | 4 | 0 |
+---+---+---+---+
| 3 | 3 | 4 | 0 |
+---+---+---+---+

是否有可以从多行读取数据并将其放在列中的函数或语句?

2 个答案:

答案 0 :(得分:2)

您的数据存储在名为entity-attribute value(EAV)的结构中。扁平化的一种方式"这是使用group bypivot

select uid,
       max(case when nid = 'x' then val end) as x,
       max(case when nid = 'y' then val end) as y,
       max(case when nid = 'z' then val end) as z
from t
group by uid;

如果您不知道结果表中所需的特定值,那么您需要动态SQL。查询更具挑战性。我建议您从Googling" SQL Server动态数据透视"。

开始

答案 1 :(得分:1)

我们可以使用Dynamic Sql实现所需的结果

IF OBJECT_ID('Tempdb..#Temp') IS NOt NUll
Drop Table #Temp
;With cte(uid,  nid, val)
AS
(
SELECT 1 , 'x', 3 UNION ALL
SELECT 2 , 'x', 3 UNION ALL
SELECT 3 , 'x', 3 UNION ALL
SELECT 1 , 'y', 4 UNION ALL
SELECT 2 , 'y', 4 UNION ALL
SELECT 3 , 'y', 4 UNION ALL
SELECT 1 , 'z', 5 
)
SELECT * INTO #Temp FRom cte

DECLARE @dynamicCol nvarchar(max),
        @Sql nvarchar(max),
        @dynamicCol2 nvarchar(max)

SELECT @dynamicCol=STUFF((SELECT DISTINCT ', ' + 'ISNULL('+nid+',''0'') AS '+QUOTENAME(nid)   FROM  #Temp
FOR XML PATH('')),1,1,'')

SELECT @dynamicCol2=STUFF((SELECT DISTINCT ', ' + QUOTENAME(nid)   FROM  #Temp
FOR XML PATH('')),1,1,'')

SET @Sql='
            SELECT [uid] , '+ @dynamicCol +' From
            (
            SELECT * From
            #temp
            )AS Src
            PIVOT 
            (
            MAX([val]) For [nid ] IN ('+@dynamicCol2+')
            )
            AS Pvt
            '

PRINT @Sql

EXEC(@Sql)

输出

uid x   y   z
--------------
1   3   4   5
2   3   4   0
3   3   4   0