我在完成MySQL查询时遇到了一些麻烦。想象一下,我将表格票证,发票行和用户组合在一起。每张票都有一个或多个发票行,每个用户可以有一张或多张票。
我正在尝试创建一个可用于创建名称徽章的查询。对于这个徽章,我需要知道该人注册的名称和项目。
我创建了以下MySQL查询
SELECT u.firstName, u.lastName, il.invID, il.name,
CASE
WHEN il.name = 'Conference Dinner'
THEN 'Diner'
END AS 'conference_dinner',
CASE
WHEN il.name = 'Regular Conference Fee' THEN 'Conference'
WHEN il.name = 'Conference Fee for Phd. Students' THEN 'Conference'
END AS 'conference',
CASE
WHEN il.name = 'Pre-Conference Fee' THEN 'Pre-Conference'
END AS 'pre_conference',
FROM invoice_line il, events_tickets et, users u
WHERE il.invID = et.invID
AND et.userID = u.ID
查询几乎没问题,但它为表中三条发票行(=三项)三条线的用户生成,我希望这三行合并为一行。用户ID上的Group By将产生一行,但是创建的列不会合并到一行中,只会显示其中一行。
我可能使用了错误的方法。但它应该产生一个这样的表:
firstName | lastName | conference_diner | conference | pre_conference |
----------------------------------------------------------------------
John | Doe | Diner | Conference | |
Jane | Norman | | Conference | Pre-Conference |
Martijn | Thomas | | Conference | |
Pete | Johns | | | Pre-Conference |
目前导致:
firstName | lastName | conference_diner | conference | pre_conference |
----------------------------------------------------------------------
John | Doe | Diner | | |
John | Doe | | Conference | |
Jane | Norman | | Conference | |
Jane | Norman | | | Pre-Conference |
Martijn | Thomas | | Conference | |
Pete | Johns | | | Pre-Conference |
提前致谢
答案 0 :(得分:2)
这样的事情:
SELECT u.firstName, u.lastName, et.invID,
CASE
WHEN il_d.name IS NULL THEN '' ELSE 'Diner'
END AS 'conference_dinner',
CASE
WHEN il_c.name IS NULL THEN '' ELSE 'Conference'
END AS 'conference',
CASE
WHEN il_p.name IS NULL THEN '' ELSE 'Pre-Conference'
END AS 'pre_conference'
FROM events_tickets et
INNER JOIN users u ON et.userID = u.ID
LEFT JOIN invoice_line il_d ON il_d.invID = et.invID AND il_d.name = 'Conference Dinner'
LEFT JOIN invoice_line il_c ON il_c.invID = et.invID AND il_c.name IN ('Regular Conference Fee', 'Conference Fee for Phd. Students')
LEFT JOIN invoice_line il_p ON il_p.invID = et.invID AND il_p.name = 'Pre-Conference Fee'
答案 1 :(得分:1)
由于您尚未包含源数据,我将假设您的最终结果中的每一列与输入数据中的一行相关。
这意味着您做想使用GROUP BY
...
SELECT
u.firstName, u.lastName, il.invID, il.name,
MAX(CASE
WHEN il.name = 'Conference Dinner' THEN 'Diner'
END) AS 'conference_dinner',
MAX(CASE
WHEN il.name = 'Regular Conference Fee' THEN 'Conference'
WHEN il.name = 'Conference Fee for Phd. Students' THEN 'Conference'
END) AS 'conference',
MAX(CASE
WHEN il.name = 'Pre-Conference Fee' THEN 'Pre-Conference'
END) AS 'pre_conference'
FROM
invoice_line il, events_tickets et, users u
WHERE
il.invID = et.invID AND et.userID = u.ID
GROUP BY
u.firstName, u.lastName
但是,我必须从il.invID, il.name,
中移除SELECT
。这是因为我推断他们可以有不同的价值观。在哪种情况下,您希望在汇总结果中显示哪个值?
修改强>:
这比多个LEFT JOIN
版本更有优势,因为它只扫描invoice_line
talb eonce,而不是多次。这个应该意味着更低的读取,可能更低的CPU,并且通常更低的执行时间。
缺点是它稍微复杂一点,如果需要,可以不那么直接地提取所有单独的il.invID
和il.name
值。
答案 2 :(得分:1)
你可以尝试这些方法:
SELECT u.firstName, u.lastName, il.invID, il.name,
IF(SUM(il.name = 'Conference Dinner') > 0,
'Diner', '') AS 'conference_dinner',
IF(SUM(il.name IN ('Regular Conference Fee',
'Conference Fee for Phd. Students')) > 0,
'Conference', '') AS 'conference',
IF(SUM(il.name = 'Pre-Conference Fee') > 0,
'Pre-Conference', '') AS 'pre_conference'
FROM invoice_line il, events_tickets et, users u
WHERE il.invID = et.invID
AND et.userID = u.ID
GROUP BY u.ID
mysql中的比较结果为数字,0表示 false ,1表示 true 。因此,您可以简单地对这些进行求和,以计算与给定表达式匹配的行。换句话说,属于单个用户的联接中的所有行都被分组,对与特定属性匹配的那些行进行计数,这些计数将决定在结果表中打印什么作为该用户的聚合值。
答案 3 :(得分:0)
在event_tickets表中添加一些自连接
SELECT u.firstName, u.lastName, il.invID, il.name,
CASE
WHEN il.name = 'Conference Dinner'
THEN 'Diner'
END AS 'conference_dinner',
CASE
WHEN il.name = 'Regular Conference Fee' THEN 'Conference'
WHEN il.name = 'Conference Fee for Phd. Students' THEN 'Conference'
END AS 'conference',
CASE
WHEN il.name = 'Pre-Conference Fee' THEN 'Pre-Conference'
END AS 'pre_conference',
FROM invoice_line il, events_tickets et1, events_tickets et2, event_tickets et3, users u
WHERE il.invID = et.invID
AND et1.userID = u.ID
AND et2.userID = u.ID
AND et3.userID = u.ID
但是还要在连接中包含一些内容,以确保您不会获得两次晚餐,例如,如果et.name是指定'Diner'与'Conferece'等属性,那么您将需要
AND et1.name > et2.Name
AND et.name > et3.name
可能还有一些空处理。