Объединение нескольких таблиц с Group_Concat, где некоторые записи существуют не во всех таблицах

Я пытаюсь выполнить довольно сложный (для меня) запрос, который будет извлекать поле "Описание" из главной таблицы, а затем добавлять к нему заголовки и значения из соответствующих справочных таблиц. Не все записи имеют записи в справочных таблицах. По мере продвижения я буду ставить дальнейшие вопросы как последующие вопросы, но для начала моя проблема заключается в том, что отображаются только те записи со значениями во всех таблицах.

http://sqlfiddle.com/

  • (ноль)
  • Это запись 2 текста

    Цвет:
    красный

    Фрукты:
    яблоко
  • (ноль)

Если я использую Concat_WS, я получаю все записи, но мой "ярлык" в concat исчезает:

http://sqlfiddle.com/

  • Это запись 1 текста

    синий
  • Это запись 2 текста

    красный
    яблоко
  • Это запись 3 текста


    виноград

Итак, мой первый шаг - получить все описания записей, независимо от того, в скольких таблицах они существуют, и отобразить имена / метки.

2 ответа

Решение

Похоже, вам нужно COALESCE:

Select J.id, 
  Concat(J.Description,
    COALESCE(Concat('<b>Color</b>:<br>',
         group_concat(F.Name SEPARATOR '<br>')),''),
    '<br>',
    COALESCE(Concat('<b>Fruit</b>:<br>',
         group_concat(F2.Name SEPARATOR '<br>')),'')

  ) AS output
from Main J
Left Join LUT_1 L          On J.ID=L.MainID
Left Join LUT_Names_1 F    On F.ID=L.LUT_NAME_ID
Left Join LUT_2 L2         On J.ID=L2.MainID
Left Join LUT_Names_2 F2   On F2.ID=L2.LUT_NAME_ID
Group by J.ID;

SQLFiddle Demo

РЕДАКТИРОВАТЬ:

Как всегда для MySQL, сам запрос основан на расширении MySQL. Если вы установите его ONLY_FULL_GROUP_BY (по умолчанию для MySQL 5.7.5 и выше):

SET sql_mode=ONLY_FULL_GROUP_BY;
-- query will return error

J.Description'нет в GROUP BY

Чтобы исправить это, вам нужно использовать функцию агрегирования в этом столбце, например: MAX:

SET sql_mode=ONLY_FULL_GROUP_BY;

Select J.id, 
Concat(MAX(J.Description),
  COALESCE(Concat('<b>Color</b>:<br>',
         group_concat(F.Name SEPARATOR '<br>')),''),
  '<br>',
  COALESCE(Concat('<b>Fruit</b>:<br>',
         group_concat(F2.Name SEPARATOR '<br>')),'')

)
from Main J
Left Join LUT_1 L          On J.ID=L.MainID
Left Join LUT_Names_1 F    On F.ID=L.LUT_NAME_ID
Left Join LUT_2 L2         On J.ID=L2.MainID
Left Join LUT_Names_2 F2   On F2.ID=L2.LUT_NAME_ID
Group by J.ID;

Я думаю concat_ws() может быть, скинуть то, что вы хотите сделать.

Следующее создает две метки, даже когда нет значений:

Select J.id, 
       Concat(J.Description,
              '<br><br>',
              '<b>Color</b>:<br>',
              coalesce(group_concat(F.Name SEPARATOR '<br>'), ''),
              '<br>',
              '<b>Fruit</b>:<br>',
              coalesce(group_concat(F2.Name SEPARATOR '<br>'), '')
             )
from Main J Left Join
     LUT_1 L
     On J.ID = L.MainID Left Join
     LUT_Names_1 F
     On F.ID = L.LUT_NAME_ID Left Join
     LUT_2 L2
     On J.ID = L2.MainID Left Join
     LUT_Names_2 F2
     On F2.ID = L2.LUT_NAME_ID
Group by J.ID, J.Description;

Вот SQL Fiddle.

Кроме того, если у вас есть несколько фруктов или цветов, вы получите дубликаты. По этой причине вы хотите distinct ключевое слово (или предварительно агрегировать по каждому измерению). Таким образом, рабочий SQL больше похож на это:

Select J.id, 
       Concat(J.Description,
              '<br><br>',
              '<b>Color</b>:<br>',
              coalesce(group_concat(distinct F.Name SEPARATOR '<br>'), ''),
              '<br>',
              '<b>Fruit</b>:<br>',
              coalesce(group_concat(distinct F2.Name SEPARATOR '<br>'), '')
             )
from Main J Left Join
     LUT_1 L
     On J.ID = L.MainID Left Join
     LUT_Names_1 F
     On F.ID = L.LUT_NAME_ID Left Join
     LUT_2 L2
     On J.ID = L2.MainID Left Join
     LUT_Names_2 F2
     On F2.ID = L2.LUT_NAME_ID
Group by J.ID, J.Description

Вот SQL Fiddle, который иллюстрирует этот момент. Просто удалите distinct и увидеть разницу в результатах.

Другие вопросы по тегам