Как объединить таблицы без использования INNER JOIN?

0

Я не умею писать MySQL-запросы, поэтому этот запрос не работает должным образом. Я хочу выбрать все "группы" и получить внешнюю информацию по группам по идентификаторам, сохраненным в группе, например, создателю группы, последнему человеку для ее обновления и количеству изображений в группе.

В этом запросе я использую INNER JOIN, но, по-видимому, группы, у которых нет изображений, выбранных в этом запросе. Я хочу, чтобы запрос выбирал ВСЕ группы, вне зависимости от того, что и какие данные извлекают из всех групп, используя идентификаторы. Если у группы нет изображений, я хочу, чтобы количество изображений было 0, а не группа, которую нужно игнорировать.

Это текущий запрос:

SELECT g.id, g.name, g.date_created, g.date_updated, g.created_by, 
    c.fullname AS creator_name, g.updated_by, u.fullname AS updater_name, COUNT(i.id) as image_count

FROM    gallery_groups g INNER JOIN 
        users c INNER JOIN 
        users u INNER JOIN 
        gallery_images i

WHERE g.created_by=c.id AND g.updated_by=u.id AND i.group=g.id $id
GROUP BY g.name
ORDER BY g.date_updated DESC, g.name

Я попытался заменить INNER JOIN на LEFT JOIN, RIGHT JOIN и OUTER JOIN, но все это приводит к ошибкам sql.

Спасибо за любую помощь!

  • 0
    Какие были ошибки?
Теги:
inner-join

2 ответа

3
Лучший ответ

Поместите критерии соединения с объединениями, где они принадлежат. Не смешивайте агрегаты (сумма/макс и т.д. По столбцам) и неагрегаты (поля не в GROUP BY, а не в функции), даже если MySQL позволяет вам

SELECT g.id, g.name, g.date_created, g.date_updated, g.created_by, 
    c.fullname AS creator_name, g.updated_by, u.fullname AS updater_name, COUNT(i.id) as image_count
FROM    gallery_groups g LEFT JOIN 
        users c ON g.created_by=c.id LEFT JOIN 
        users u ON g.updated_by=u.id LEFT JOIN
        gallery_images i ON i.group=g.id
WHERE g.id = $id
GROUP BY g.id, g.name, g.date_created, g.date_updated, g.created_by, 
    c.fullname, g.updated_by, u.fullname
ORDER BY g.date_updated DESC, g.name

Поскольку вы группируете практически все остальное, кроме количества изображений, может быть лучше просто подзапрос, который

SELECT g.id, g.name, g.date_created, g.date_updated, g.created_by, 
    c.fullname AS creator_name, g.updated_by, u.fullname AS updater_name,
    IFNULL((
        select COUNT(1)
        from gallery_images i
        WHERE i.group=g.id), 0) as image_count
FROM    gallery_groups g LEFT JOIN 
        users c ON g.created_by=c.id LEFT JOIN 
        users u ON g.updated_by=u.id LEFT JOIN
        gallery_images i ON i.group=g.id
WHERE g.id = $id
ORDER BY g.date_updated DESC, g.name
1

Когда вы присоединяетесь к двум таблицам в SQL, вы даете критерии для присоединения.

SELECT g.id, g.name, g.date_created, g.date_updated, g.created_by, 
c.fullname AS creator_name, g.updated_by, u.fullname AS updater_name, COUNT(i.id) as image_count
FROM    gallery_groups g 
    INNER JOIN users c ON g.created_by=c.id
    INNER JOIN users u ON g.updated_by=u.id
    INNER JOIN gallery_images i ON i.group=g.id
GROUP BY g.name
ORDER BY g.date_updated DESC, g.name

Предложение FROM выполняется первым и собирает все данные, которые будут возвращены запросом. Затем выполняются предложения GROUP BY и WHERE, которые уменьшают количество строк, которые будут возвращены. Наконец, выполняется предложение ORDER BY, которое перестраивает весь результирующий набор.

Разница между внутренним и внешним соединениями - это поведение, когда происходят несоответствия. Внутренние соединения отбрасывают строки, которые несовместимы, внешние соединения допускают несоответствия. Вы почти всегда хотите внутреннее соединение, если у вас нет причин, по которым вам нужно внешнее соединение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню