суббота, 1 октября 2011 г.

MySQL.JOIN.примеры.

В данном посте будет рассмотренно несколько возможных применений LEFT JOIN, INNER JOIN и HAVING для запросов к MySQL.

По ходу текста будут внесены некоторые коментарии и результаты выполнения.
Небольшая база с основной информацией:
  • authors {id, name}   Отобразить дамп
  • books {id, name}   Отобразить дамп
  • library {id, auth_id, book_id}   Отобразить дамп
Полный дамп базы можно почитать тут

И так,преступим составлению запросов.
Имена авторов с указанием кол-ва книг
SELECT a.name, COUNT(l.book_id) bcount
FROM authors a
LEFT JOIN library l ON l.auth_id = a.id 
GROUP BY a.id
ORDER BY bcount DESC
name bcount
Николай Андреев 5
Сергей Лукьяненко 2
Роман Злотников 0

Авторы у которых более 3 книг.
SELECT a.name, count(l.id) bcount
FROM authors a
LEFT JOIN library l ON l.auth_id = a.id
GROUP BY a.id
HAVING bcount > 3
ORDER BY bcount DESC
name bcount
Николай Андреев 5

Авторы без книг
SELECT a.name
FROM authors a
LEFT JOIN library l ON l.auth_id = a.id
WHERE l.auth_id IS NULL
name
Роман Злотников
Аналогично можно составить запрос для выявления книг, которые не занесены в блиблиотеку.

Логическим завершением будет Список книг библиотеки
SELECT b.name, a.name
FROM library l
LEFT JOIN authors a ON l.auth_id = a.id
LEFT JOIN books b ON l.book_id = b.id
name name
Мир героев Николай Андреев
Яд для живых Николай Андреев
Сектор мутантов Николай Андреев
Геном Сергей Лукьяненко
Танцы на снегу Сергей Лукьяненко
Танцы на снегу Николай Андреев
Лучшие из мертвых Николай Андреев

И результат оказался несовсем красивым, хотя вполне ожидаемым.
Данный запрос читается так:
"Выбрать назнание книг из таблицы books и имена авторов из таблицы authors для всех записей из таблицы library при условии соответствия l.auth_id = a.id и l.book_id = b.id."
Первым делом изменим выборку для большей логичности
- SELECT b.name, a.name
+ SELECT b.name book, a.name author
Таким образом заголовок "name , name" изменится на необходимый нам "book, author"
Если мы изменим запрос к виду:
 SELECT b.name book , 
 (
  SELECT a.name FROM authors a
  LEFT JOIN library l ON l.auth_id = a.id
  WHERE l.book_id = b.id
 ) author
 FROM books b
Получим ошибку вида "Subquery returns more than 1 row", что лишний раз доказыват, необходимость решения этой проблемы на стороне php и в контекст даного поста не входит.
Перый конечный вид запроса:
SELECT b.name book, a.name author
FROM library l
LEFT JOIN authors a ON l.auth_id = a.id
LEFT JOIN books b ON l.book_id = b.id
Следует помнить, что в результате этого запроса возможны "NULL" значения в полях book и author.
Второй конечный вид запроса:
SELECT b.name book, a.name author
FROM library l
INNER JOIN authors a ON l.auth_id = a.id
INNER JOIN books b ON l.book_id = b.id
Следует помнить, что в лучае такого запроса проверется обязательное соответствие условий "ON". Например удаление автора приведет к неотображению всех книг, для которых автор является единственным.
book author
Мир героев Николай Андреев
Яд для живых Николай Андреев
Сектор мутантов Николай Андреев
Геном Сергей Лукьяненко
Танцы на снегу Сергей Лукьяненко
Танцы на снегу Николай Андреев
Лучшие из мертвых Николай Андреев


Дополнительно по теме:
Если кого-то таки заинтересует более подробная информация дайте знать, дополню.

Комментариев нет:

Отправить комментарий