我在MySQL中有多对多的表关系,涉及三个表:tickets
,ticket_solutions
和solutions
。 (票证可能有多个解决方案,解决方案适用于多个票证。)
以下是表结构,简化:
tickets ticket_solutions solutions
----- ----- -----
id ticket_id id
solution_id solution
(在此示例中,所有字段均为INT
,solutions.solution
除外VARCHAR
。)由于某些故障单未完成,因此可能没有任何解决方案。
我写了以下查询:
SELECT t.id, GROUP_CONCAT(DISTINCT sol.solution SEPARATOR ', ') solutions
FROM tickets t
LEFT JOIN ticket_solutions tsol ON (tsol.ticket_id = t.id)
LEFT JOIN solutions sol ON (tsol.solution_id = sol.id)
GROUP BY t.id DESC;
我的问题在于第二个LEFT JOIN
。在给定票证的链接器表(ticket_solutions
)中存在条目的任何情况下,总是是要在solutions
中匹配的记录。但是,如果我尝试使用INNER JOIN
,我将不再获得缺少解决方案的门票。
根据我的想法,NULL
值和链接器表之间的关系只会出现tickets
值。 (没有任何解决方案的票证。)
我必须在链接器表和LEFT JOIN
之间使用solutions
,即使该特定关系中没有NULL
值吗?
如果没有,建议的查询结构是什么?
答案 0 :(得分:7)
以这种方式尝试:
SELECT t.id, GROUP_CONCAT(DISTINCT sol.solution SEPARATOR ', ') solutions
FROM tickets t
LEFT JOIN ticket_solutions tsol
INNER JOIN solutions sol
ON (tsol.solution_id = sol.id)
ON (tsol.ticket_id = t.id)
GROUP BY t.id DESC;
答案 1 :(得分:1)
在您的原始SQL中,您将ticket_solutions的门票连接起来,然后将生成的视图内部连接到解决方案,这将解决没有相应解决方案的行。
在Joe Stefanelli的回答中,也可以写成
SELECT t.id, GROUP_CONCAT(DISTINCT sol.solution SEPARATOR ', ')
FROM tickets t
LEFT JOIN
(SELECT ticket_solutions.ticket_id AS id, solutions.solution AS solution
FROM ticket_solutions tsol
INNER JOIN solutions ON ticket_solutions.solution_id=solutions.id
) AS sol ON t.id=sol.id
您首先将ticket_solutions内部加入解决方案,然后将结果视图左键连接到票证,从而不会压制空票。
答案 2 :(得分:0)
Joe Stefanelli的答案是绝对正确的。 只是想补充一点,你可以使用
IFNULL(GROUP_CONCAT(DISTINCT sol.solution SEPARATOR ', '), '')
有一个空字符串而不是空字符。
然而,由于关于同一问题的其他一些讨论令人困惑,所以也想把这个小提琴联系起来:http://www.sqlfiddle.com/#!2/54c6f/3/0