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

Beavis

Banned
Постраничный вывод результата сложного запроса

Делаю базу данных для хранения информации о книгах.

В упрощенном варианте она выглядит так:

таблица books
id_book
name

таблица authors
id_author
surname
name

таблица books_authors
id_author
id_book

запрос на выборку книг выглядит так:
[SQL]
SELECT `b`.`id_book` , `b`.`name` , TRIM( CONCAT_WS( ' ', `a`.`surname` , `a`.`name` )) AS `author` FROM ((`books` AS `b` )LEFT JOIN `books_authors` AS `ba` ON `b`.`id_book` = `ba`.`id_book` ) LEFT JOIN `authors` AS `a` ON `a`.`id_author` = `ba`.`id_author` ORDER BY `name` [/SQL]

результатом этого запроса является следующее отображение:

id_book | name | author
1 | Книга1 | Автор1
1 | Книга1 | Автор2
2 | Книга2 | Автор3
2 | Книга2 | Автор4
2 | Книга2 | Автор5
3 | Книга3 | Автор3
3 | Книга3 | Автор8

после получения данного результата он обрабатывается в PHP и результат выводится в виде:
Книга 1 (Автор1, Автор2)
Книга 2 (Автор3, Автор4)
Книга 3 (Автор3, Автор8)

На самом деле в базе и таблиц гораздо больше, и связей, и столбцов в вышеуказанных таблицах.

Всё было прекрасно до того момента как я захотел сделать постраничный вывод всего этого дела, т.е. по N записей на странице... простым LIMIT'ом в запросе тут не обойтись, т.к. одной книге соответствует несколько строк в таблице результата

Есть вариант всё время выбирать все записи а с помощью PHP выводить нужные, но я не знаю насколько это будет ресурсоемко при больших объемах БД.

Какие есть варианты ? :)
 

Gas

может по одной?
схематично так:
[sql]
select *
from (select * from books order by name LIMIT offset,count) as b
LEFT JOIN `books_authors` AS `ba` ON `b`.`id_book` = `ba`.`id_book` )
LEFT JOIN `authors` AS `a` ON `a`.`id_author` = `ba`.`id_author`
[/sql]
 

FractalizeR

Новичок
Почему нет?

Просто вот это
после получения данного результата он обрабатывается в PHP и результат выводится в виде:
Книга 1 (Автор1, Автор2)
Книга 2 (Автор3, Автор4)
Книга 3 (Автор3, Автор8)
Лучше делать с помошью, скажем, GROUP_CONCAT, чтобы в MySQL сразу нормальный результат получался. Тогда все должно нормально работать.
 

Gas

может по одной?
FractalizeR
Ok, действительно лучше заменить "никак не использовать" на "лучше не использовать".
1. Вариант c отдельным запросом COUNT(*) по таблице books (myisam и без условий), будет намного быстрее (чем больше записей, тем разница существенней) чем одни запрос с SQL_CALC_FOUND_ROWS.
2. Если же использовать SQL_CALC_FOUND_ROWS, то нужно делать группировку над всем набором записей books<->authors, этого в данном случае можно и нужно избегать.

Что касается GROUP_CONCAT, думаю для автора может быть ценной информацией. Можно добавить группировку и GROUP_CONCAT в мой запрос.
 

Beavis

Banned
вот за GROUP_CONCAT спасибо! забыл я чё-то совсем про неё, даже на php пришлось аналог ей написать))
 

FractalizeR

Новичок
Автор оригинала: Gas
FractalizeR
Ok, действительно лучше заменить "никак не использовать" на "лучше не использовать".
1. Вариант c отдельным запросом COUNT(*) по таблице books (myisam и без условий), будет намного быстрее (чем больше записей, тем разница существенней) чем одни запрос с SQL_CALC_FOUND_ROWS.
Согласен, но я полагаю, что запрос в жизни включает в себя условие WHERE. Просто автором он был приведен в упрощенном варианте.

Автор оригинала: Gas 2. Если же использовать SQL_CALC_FOUND_ROWS, то нужно делать группировку над всем набором записей books<->authors, этого в данном случае можно и нужно избегать.
Тоже согласен.
 
Сверху