В данном посте будет рассмотренно несколько возможных применений
LEFT JOIN, INNER JOIN и HAVING для запросов к MySQL.
По ходу текста будут внесены некоторые коментарии и результаты выполнения.
Небольшая база с основной информацией:
И так,преступим составлению запросов.
Имена авторов с указанием кол-ва книг
Авторы у которых более 3 книг.
Авторы без книг
Аналогично можно составить запрос для выявления книг, которые не занесены в блиблиотеку.
Логическим завершением будет Список книг библиотеки
И результат оказался несовсем красивым, хотя вполне ожидаемым.
Данный запрос читается так:
"Выбрать назнание книг из таблицы books и имена авторов из таблицы authors для всех записей из таблицы library при условии соответствия l.auth_id = a.id и l.book_id = b.id."
Первым делом изменим выборку для большей логичности
Если мы изменим запрос к виду:
Перый конечный вид запроса:
Второй конечный вид запроса:
Дополнительно по теме:
Если кого-то таки заинтересует более подробная информация дайте знать, дополню.
По ходу текста будут внесены некоторые коментарии и результаты выполнения.
Небольшая база с основной информацией:
- authors {id, name}   Отобразить дамп Скрыть дамп
- books {id, name}   Отобразить дамп Скрыть дамп
- library {id, auth_id, book_id}   Отобразить дамп Скрыть дамп
--
-- Структура таблицы `books`
--
CREATE TABLE IF NOT EXISTS `books` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(75) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251;
--
-- Дамп данных таблицы `books`
--
INSERT INTO `books`
(`id`, `name`)
VALUES
(1, 'Мир героев'),
(2, 'Лучшие из мертвых'),
(3, 'Яд для живых'),
(4, 'Сектор мутантов'),
(5, 'Геном'),
(6, 'Танцы на снегу'),
(7, 'Сос по прозвищу Верёвка');
--
-- Структура таблицы `library`
--
CREATE TABLE IF NOT EXISTS `library` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`auth_id` int(11) NOT NULL,
`book_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251;
--
-- Дамп данных таблицы `library`
--
INSERT INTO `library`
(`auth_id`, `book_id`)
VALUES
(1, 1),
(1, 3),
(1, 4),
(2, 5),
(2, 6),
(1, 6),
(1, 2);
И так,преступим составлению запросов.
Имена авторов с указанием кол-ва книг
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 |
|---|---|
| Мир героев | Николай Андреев |
| Яд для живых | Николай Андреев |
| Сектор мутантов | Николай Андреев |
| Геном | Сергей Лукьяненко |
| Танцы на снегу | Сергей Лукьяненко |
| Танцы на снегу | Николай Андреев |
| Лучшие из мертвых | Николай Андреев |
Дополнительно по теме:
Если кого-то таки заинтересует более подробная информация дайте знать, дополню.
Комментариев нет:
Отправить комментарий