展平EAV类型SQL查询

时间:2013-05-30 15:23:36

标签: mysql sql entity-attribute-value

我有一个用于邮件列表的MySQL数据库,我需要提取数据,因此一个成员记录由一行表示。邮件列表将用户属性存储为EAV。我可以使用以下SQL查询提取所需的所有详细信息,但每个成员记录占用多行:

SELECT a.id, a.name, a.email, b.id, b.name, b.email, c.title, d.val
FROM lists a, listmembers b, fields c, fieldsdata d
WHERE a.id = b.nl
AND b.id = d.eid
AND c.id = d.fid
ORDER BY b.id, a.id, b.name

返回如下内容:

'6', 'Mailing List name', 'owner@mailinglist.com', '10478', 'username', 'mailinglistmember@emailaddress.com', 'Firstname', 'John'
'6', 'Mailing List name', 'owner@mailinglist.com', '10478', 'username', 'mailinglistmember@emailaddress.com', 'Lastname', 'Smith'
'6', 'Mailing List name', 'owner@mailinglist.com', '10478', 'username', 'mailinglistmember@emailaddress.com', 'Country', 'UK'
'6', 'Mailing List name', 'owner@mailinglist.com', '10478', 'username', 'mailinglistmember@emailaddress.com', 'Town', 'Cambridge'
'6', 'Mailing List name', 'owner@mailinglist.com', '10478', 'username', 'mailinglistmember@emailaddress.com', 'Shoesize', '7'
'6', 'Mailing List name', 'owner@mailinglist.com', '10478', 'username', 'mailinglistmember@emailaddress.com', 'Favourite Colour', 'Purple'

我需要使用SQL将其展平为一行,只需要与键名字,姓氏,城镇和国家/地区相关的值

数据库不是很大,fieldsdata表是最大的,有大约5500行。

看起来像是一个真正的痛苦,所以任何指针都会感激不尽。 !

3 个答案:

答案 0 :(得分:2)

如果我正确理解您的问题,您可以MAXCASE一起展示您的搜索结果:

SELECT l.id, l.name, l.email, lm.id, lm.name, lm.email, 
   MAX(CASE WHEN f.title = 'Firstname' THEN fd.val END) FirstName,
   MAX(CASE WHEN f.title = 'Lastname' THEN fd.val END) Lastname,
   MAX(CASE WHEN f.title = 'Country' THEN fd.val END) Country,
   MAX(CASE WHEN f.title = 'Town' THEN fd.val END) Town
FROM lists l
   JOIN listmembers lm ON l.id=lm.nl
   JOIN fieldsdata fd ON fd.eid = lm.id
   JOIN fields f ON f.id = fd.fid 
GROUP BY l.id, lm.id

这假设您的列表中的id字段是您的唯一标识符。如果没有,您需要向GROUP BY添加其他字段(很可能是listmembers表中的id字段)。

答案 1 :(得分:2)

对于发现此问题的任何人(像我一样),您的查询与SQL Server而不是MySQL相关,可以选择Pivot查询。

SELECT id, name, email, id2, name2, email2, [Firstname], [Lastname], 
    [Country], [Town]
FROM (select id, name, email, id2, name2, email2, title, val from yourresults) ps
PIVOT (
        MAX(val) 
        FOR title IN ([Firstname], [Lastname], [Country], [Town])
    ) as pvt

请参阅SQL fiddle(使用上面的sgeddes SQL小提琴 - 谢谢)

或在MS Access中:

TRANSFORM Max(val)
SELECT id, name, email, id2, name2, email2
FROM yourresults
GROUP BY id, name, .email, id2, name2, email2
PIVOT title In ("FirstName","LastName","Country","Town");

答案 2 :(得分:-2)

EAV表是一种糟糕的设计选择,只有在您事先无法知道需要哪些字段时才应使用。诸如firstname之类的字段可以预先知道您将需要它们并且应该在适当的相关表中。如果您想使用EAV,至少停止使用关系数据库并使用为此设计的NOSQL数据库。

要获得您想要的结果,您需要为每种类型的数据加入EAV表一次。