我是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 |
+---+---+---+---+
是否有可以从多行读取数据并将其放在列中的函数或语句?
答案 0 :(得分:2)
您的数据存储在名为entity-attribute value(EAV)的结构中。扁平化的一种方式"这是使用group by
或pivot
:
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