2

我有一个用于邮件列表的 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 行。

似乎是一种真正的痛苦,所以任何指点都会感激不尽。!

4

3 回答 3

3

对于在查询与 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 fiddle 工作 - 谢谢)

或在 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");
于 2014-03-27T01:01:29.630 回答
2

You can use MAX with CASE to pivot your results if I'm understanding your question correctly:

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

This assumes the id field from your lists table is your unique identifier. If not, you'll need to add additional fields to your GROUP BY (most likely the id field from your listmembers table).

于 2013-05-30T15:33:11.887 回答
-3

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

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

于 2013-05-30T15:30:02.870 回答