Как объединить таблицы без использования INNER JOIN? - PullRequest
0 голосов
/ 20 января 2011

Я плохо умею писать запросы 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.

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

Ответы [ 2 ]

3 голосов
/ 20 января 2011

Поместите критерии объединения с теми соединениями, к которым они принадлежат.Не смешивайте агрегаты (сумма / макс и т. Д. В столбцах) и неагрегаты (поля не в 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 голос
/ 20 января 2011

Когда вы объединяете две таблицы в 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, которое переупорядочивает весь набор результатов.

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

...