【问题标题】:SQL Using PIVOT for multi valued attributesSQL 使用 PIVOT 处理多值属性
【发布时间】:2017-04-25 06:03:26
【问题描述】:

我设计了一个 EAV 表,如下所示:

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

也是一个映射属性的表:

AttributeID AttributeName
    1            Hobbies
    2            Name
    3            Gender
    4            IrisColor

在第一个表上使用pivot后,链接到属性表:

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(即爱好)在第一个表(SubjectDetails)中又出现了一次,所以我想要实现的是:

SubjectID Hobbies Name Gender IrisColor
    1        **1,2**      1     2      3

我不得不提一下,我不关心使用什么分隔符,我尝试使用 STUFF 函数来做到这一点,但是将 PIVOT 和 STUFF 结合起来很痛苦(或者我只是不知道如何)..有什么建议吗?

【问题讨论】:

  • 您可以修改源 EAV 表,使其每个属性有一行,并使用逗号分隔值,然后使用您的数据透视查询进行数据透视。
  • 我不能这样做.. 要求是每个属性都有单独的行,即使它重复。我只是不想在视图中这样做,而不是像用逗号分隔那样存储它

标签: sql-server database pivot rows multivalue


【解决方案1】:

这应该可行,我做了以下事情: 将您的 EAV 表 (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

【讨论】:

  • 非常好! :) 编码愉快!
  • 还有一个问题,最好的方法是创建视图还是每次都重新创建表?
  • 视情况而定,但如果数据不经常更改,您可以将其保留在视图中。您也可以尝试这两种情况并找出哪个更快!临时表肯定会每次都起作用。你可以看看这个答案(stackoverflow.com/questions/16897323/…)。
  • 好的,关于解决方案,我还想尝试用我编写的另一个聚合函数替换“MAX”函数,它连接给定的列
【解决方案2】:

不使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多