SQL SELECT 来自和 EAV table

SQL SELECT from and EAV table

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

  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 

和属性 table

Attributes
  ID Description
   1 SkinColor 
   2 IrisColor 
   3 Gender

还有 EAV table:

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

因此,如果我只想 select 名称、属性名称和 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

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

以前我知道我想从 SkinColor select 该值,但在 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。我该如何继续?

您的数据模型有点神秘,因为您在 "person details" table 中的 ID 不能具有适当的外键关系。您可以 将所有属性放在同一个table 中。或者每个属性都有一个单独的 table。或者——与 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';

我猜你需要动态 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);

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

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