2017-06-20 58 views
0

我是一名SQL初学者,并且有一个问题。我有用户数据的表像这样SQL Server从表中获取行并显示在列中

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 | 
+---+---+---+---+ 

是否有功能或可以从多个行读取数据,并把它列报表?

+7

阅读有关'PIVOT'或*有条件聚集* – Shnugo

回答

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。该查询更具挑战性。我建议你从谷歌搜索“SQL Server动态数据透视表”开始。

+0

将这项工作如果VAL是不同的UID不同? – Nithin

+0

@Nithin。 。 。是。它将为没有值的ID返回NULL。 –

1

我们可以使用动态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 ('[email protected]+') 
      ) 
      AS Pvt 
      ' 

PRINT @Sql 

EXEC(@Sql) 

输出

uid x y z 
-------------- 
1 3 4 5 
2 3 4 0 
3 3 4 0 
相关问题