使用左外连接进行允许为null的多对多关系

时间:2011-12-16 19:33:52

标签: mysql many-to-many

我在MySQL中有多对多的表关系,涉及三个表:ticketsticket_solutionssolutions。 (票证可能有多个解决方案,解决方案适用于多个票证。)

以下是表结构,简化:

tickets    ticket_solutions    solutions
-----      -----               -----
id         ticket_id           id
           solution_id         solution

(在此示例中,所有字段均为INTsolutions.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值吗?

如果没有,建议的查询结构是什么?

3 个答案:

答案 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