SQL 对多值属性使用 PIVOT
SQL Using PIVOT for multi valued attributes
我设计了一个 EAV table,看起来像这样:
SID AID VID
1 1 1
1 2 1
1 3 2
1 4 3
1 1 2
SID代表Subject ID,AID代表Attribute ID,VID代表ValuedID
还有一个table来映射属性:
AttributeID AttributeName
1 Hobbies
2 Name
3 Gender
4 IrisColor
在第一个 table 上使用 pivot 后,链接到属性 table:
SELECT
SubjectID,
Hobbies,
Name,
Gender,
IrisColor
FROM
(
SELECT SubjectID, attr.AttributeName as attribute, ValueID from SubjectDetails, SubjectAttributes as attr WHERE SubjectDetails.AttributeID=attr.ID
) as t
PIVOT(
MAX(ValueID)
FOR attribute IN (Hobbies,Name,Gender,IrisColor)) AS t1
WHERE SubjectID=1
我明白了:
SubjectID Hobbies Name Gender IrisColor
1 1 1 2 3
这几乎是正确的,但是SubjectAttribute 1(即爱好)在第一个table(SubjectDetails)中出现了一次,所以我想要实现的是:
SubjectID Hobbies Name Gender IrisColor
1 **1,2** 1 2 3
我不得不提一下,我不关心使用什么分隔符,我尝试使用 STUFF 函数来做到这一点,但是将 PIVOT 和 STUFF 结合起来很痛苦(或者我只是不知道如何) ..有什么建议吗?
这应该可行,我做了以下操作:
将来自您的 EAV table (table1
) 的信息作为每行 SID
存储到 temporary table
中(您可以创建一个 view
)。
然后按如下方式对该结果集进行透视(使用您的透视查询):
SELECT *
FROM
(
SELECT * from #temptbl
) as t
PIVOT( MAX(vid) FOR attrname IN (Hobbies,Name,Gender,IrisColor)) AS t1
WHERE sid=1
我得到了这个结果:
请检查完整的工作版本here。
这个不用PIVOT也行,我觉得这里没必要用PIVOT
SELECT SubjectID
,+STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'Hobbies'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS Hobbies
,STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'Name'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS Name
,STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'Gender'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS Gender
,STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'IrisColor'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS IrisColor
FROM @T_SubjectDetails H
GROUP BY SubjectID
我设计了一个 EAV table,看起来像这样:
SID AID VID
1 1 1
1 2 1
1 3 2
1 4 3
1 1 2
SID代表Subject ID,AID代表Attribute ID,VID代表ValuedID
还有一个table来映射属性:
AttributeID AttributeName
1 Hobbies
2 Name
3 Gender
4 IrisColor
在第一个 table 上使用 pivot 后,链接到属性 table:
SELECT
SubjectID,
Hobbies,
Name,
Gender,
IrisColor
FROM
(
SELECT SubjectID, attr.AttributeName as attribute, ValueID from SubjectDetails, SubjectAttributes as attr WHERE SubjectDetails.AttributeID=attr.ID
) as t
PIVOT(
MAX(ValueID)
FOR attribute IN (Hobbies,Name,Gender,IrisColor)) AS t1
WHERE SubjectID=1
我明白了:
SubjectID Hobbies Name Gender IrisColor
1 1 1 2 3
这几乎是正确的,但是SubjectAttribute 1(即爱好)在第一个table(SubjectDetails)中出现了一次,所以我想要实现的是:
SubjectID Hobbies Name Gender IrisColor
1 **1,2** 1 2 3
我不得不提一下,我不关心使用什么分隔符,我尝试使用 STUFF 函数来做到这一点,但是将 PIVOT 和 STUFF 结合起来很痛苦(或者我只是不知道如何) ..有什么建议吗?
这应该可行,我做了以下操作:
将来自您的 EAV table (table1
) 的信息作为每行 SID
存储到 temporary table
中(您可以创建一个 view
)。
然后按如下方式对该结果集进行透视(使用您的透视查询):
SELECT *
FROM
(
SELECT * from #temptbl
) as t
PIVOT( MAX(vid) FOR attrname IN (Hobbies,Name,Gender,IrisColor)) AS t1
WHERE sid=1
我得到了这个结果:
请检查完整的工作版本here。
这个不用PIVOT也行,我觉得这里没必要用PIVOT
SELECT SubjectID
,+STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'Hobbies'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS Hobbies
,STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'Name'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS Name
,STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'Gender'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS Gender
,STUFF((SELECT ', '+CAST(ValueID AS NVARCHAR)
FROM @T_SubjectAttributes A
INNER JOIN @T_SubjectDetails B ON A.AttributeID = B.AttributeId
WHERE AttributeName = 'IrisColor'
AND B.SubjectID = H.SubjectID FOR XML PATH(''))
,1,2,'') AS IrisColor
FROM @T_SubjectDetails H
GROUP BY SubjectID