Использование левого внешнего соединения для отношений «многие ко многим», где допускается нулевое значение - PullRequest
5 голосов
/ 16 декабря 2011

У меня есть отношение ко многим к многим таблицам в 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;

Myвопрос со вторым LEFT JOIN.В любой ситуации, когда существует запись в таблице компоновщика (ticket_solutions) для данного тикета, всегда будет записью, которая будет соответствовать solutions.Однако, если я попытаюсь использовать INNER JOIN вместо этого, я больше не получу билеты, в которых нет решений.

На мой взгляд, единственное время, когда значения NULL будут иметь место, находится в отношениях между tickets итаблица линкеров.(Билет еще не найден.)

Должен ли я использовать LEFT JOIN между таблицей компоновщика и solutions, даже если в этом конкретном отношении не будет значений NULL?

Если нет, какова рекомендуемая структура запроса?

Ответы [ 3 ]

7 голосов
/ 16 декабря 2011

Попробуйте так:

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 голос
/ 16 декабря 2011

В исходном SQL-коде вы оставили соединение тикетов в ticket_solutions, а затем внутреннее соединение результирующего представления с решениями, которые будут подавлять строки без соответствующего решения.

В ответе Джо Стефанелли, который также можно записать как

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 к решениям, затем присоединяете слева к полученному представлению к заявкам, таким образом, НЕ подавляя пустые заявки.

0 голосов
/ 21 февраля 2013

Ответ Джо Стефанелли абсолютно прав. Просто хотел добавить, что вы можете использовать

IFNULL(GROUP_CONCAT(DISTINCT sol.solution SEPARATOR ', '), '')

иметь пустую строку вместо нуля.

Однако, поскольку некоторые другие дискуссии по той же проблеме сбивают с толку, просто хотел также связать эту скрипку:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...