【问题标题】:SQL SELECT from and EAV tableSQL SELECT from 和 EAV 表
【发布时间】:2017-02-27 10:57:41
【问题描述】:

根据我之前的问题,我有以下表格:

  IrisColor 
  ID Description
   1 Blue 
   2 Gray 
   3 Green 
   4 Brown

 SkinColor 
  ID Description
   1 White 
   2 Asian 
   3 Dark       

Gender
  ID Description
   1 Male 
   2 Female 

还有属性表

Attributes
  ID Description
   1 SkinColor 
   2 IrisColor 
   3 Gender

还有 EAV 表:

PersonDetails
  PersonID AttributeID ValueID
   121       1            1
   121       2            2
   121       3            1
   122       1            2
   122       2            1
   122       3            1

因此,如果我想选择名称、属性名称和仅为 SkinColor 的值,我会这样做:

SELECT p.Name,
       a.Description,
       v.Description
       FROM PersonDetails AS sd 
       INNER JOIN Subjects AS p ON sd.PersonID=p.ID 
       INNER JOIN SubjectAttributes AS a ON sd.AttributeID=a.ID
       INNER JOIN SkinColor AS v ON sd.ValueID= v.ID

但是如果我想从数据库中选择所有人的所有信息,不仅是肤色,还有虹膜颜色和性别,我该怎么办?

以前我知道我想从 SkinColor 中选择那个值,但在 PersonDetails 中我也有 IrisColor 和 Gender 的值。

INNER JOIN SkinColor AS v ON sd.ValueID= v.ID 这将不再适用。如何用更动态的东西代替它?

更新:

我用了这个说法:

SELECT
    SubjectID,
    SkinColor,
    IrisColor,
    EyeLidFlisure,
    KnownEyeDeffect,
    Ethnicity,
    Height,
    DrivingLicense,
    Gender
FROM
(
SELECT SubjectID, attr.Description as attribute, ValueID from SubjectDetails, SubjectAttributes as attr WHERE SubjectDetails.AttributeID=attr.ID
) as t
PIVOT(MAX(ValueID) FOR attribute IN (SkinColor,IrisColor,Gender,EyeLidFlisure,KnownEyeDeffect,Ethnicity,Height,DrivingLicense)) AS t1

现在,我在单独的列中列出了所有属性,但我有值 ID,而不是值描述。我应该如何继续?

【问题讨论】:

  • 将 EAV 转入常规表 PersonDetailsT(PersonID,SkinColor,IrisColor , Gender ...) 并将其加入适当的表。 Pivot 是特定于 DBMS 的,请正确标记 DBMS。
  • 您能更具体地谈谈加入部分吗?因为这正是我现在的问题。
  • 你的 DBMS 是什么?
  • SQL Express + Microsoft sql server 管理工作室
  • 为什么要将属性存储在单独的表中?这似乎是 EAV 模型的一个奇怪实现。通常这些值直接进入表格?

标签: sql database attributes sql-server-express entity-attribute-value


【解决方案1】:

您的数据模型有点神秘,因为您在“人员详细信息”表中的 id 不能具有正确的外键关系。您可以将所有属性放在同一个表中。或者为每个属性设置一个单独的表。或者 - 与 EAV 模型一样 - 将描述直接放入 PersonDetails

你需要做这样的事情:

SELECT p.Name,
       sa.Description,
       ic.Description as IrisColor,
       g.Description as gender
FROM PersonDetails sd INNER JOIN
     Subjects p
     ON sd.PersonID = p.ID INNER JOIN
     SubjectAttributes sa
     ON sd.AttributeID = sa.ID 
     ON  LEFT JOIN
     SkinColor sc
     ON sd.ValueID = sc.ID AND sa.Description = 'SkinColor' LEFT JOIN
     IrisColor ic
     ON sd.ValueId = ic.ID AND sa.Description = 'IrisColor' LEFT JOIN
     Gender g
     ON sd.ValueId = g.ID AND sa.Description = 'Gender';

【讨论】:

    【解决方案2】:

    猜你需要从属性字典构建的动态 sql

    declare @sql varchar(max)=
      'select PersonID , ' +
      +  stuff((select ','+Description + '.Description as ' + Description
                 from Attributes
            for xml path ('')),1,1,'')
      + ' from (select PersonID, '
      +  stuff((select ',max(case AttributeID when ' + cast(ID as varchar(5)) +' then ValueID end) as ' + Description
            from Attributes
            for xml path ('')),1,1,'')
      +' from PersonDetails group by PersonID ) pvt' 
      +  (select ' left join ' + Description + ' on pvt.' + Description + ' = '+ Description + '.ID'
            from   Attributes
            for xml path (''));
    
    exec (@sql);
    

    【讨论】:

      【解决方案3】:

      这将是完整的解决方案(不知道它是否是最简单的......但它有效)

      WITH Subject AS (
      
      SELECT
          SubjectID,
          SkinColor,
          IrisColor,
          EyeLidFlisure,
          KnownEyeDeffect,
          Ethnicity,
          Height,
          DrivingLicense,
          Gender
      FROM
      (
      SELECT SubjectID, attr.Description as attribute, ValueID from SubjectDetails, SubjectAttributes as attr WHERE SubjectDetails.AttributeID=attr.ID
      ) as t
      PIVOT(MAX(ValueID) FOR attribute IN (SkinColor,IrisColor,Gender,EyeLidFlisure,KnownEyeDeffect,Ethnicity,Height,DrivingLicense)) AS t1
      )
      
      SELECT SubjectID,
      whole.Name as Name,
      whole.eMail as eMail,
      skincolor.Description as SkinColor, 
      iriscolor.Description as IrisColor,
      eyelid.Description as EyeLidFlisure,
      defect.Description as KnownEyeDeffect,
      eth.Description as Ethnicity,
      height.Description as Height,
      dl.Description as DrivingLicense,
      gender.Description as Gender
      
      FROM Subject S
      Left JOIN Subjects whole ON whole.ID=S.SubjectID
      Left JOIN SkinColor skincolor ON S.SkinColor=skincolor.ID
      Left JOIN IrisColor iriscolor ON S.IrisColor=iriscolor.ID
      Left JOIN EyeLidFlisure eyelid ON S.EyeLidFlisure=eyelid.ID
      Left JOIN KnownEyeDeffect defect ON S.KnownEyeDeffect=defect.ID
      Left JOIN Ethnicity eth ON S.Ethnicity=eth.ID
      Left JOIN Height height ON S.Height=height.ID
      Left JOIN DrivingLicense dl ON S.DrivingLicense=dl.ID
      Left JOIN Gender gender ON S.Gender=gender.ID
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-12
        • 1970-01-01
        • 1970-01-01
        • 2016-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多