简体   繁体   中英

MySQL limiting rows in a many-to-many relationship

i have a database with 3 tables in a many-to-many relationship. one is the books , the other is the authors and the third is their junction (used to join the two). the database is MySQL

a book can be made by many authors, and authors make many books.

在此输入图像描述

now i want to get the books (with authors) like say 8 books at a time. i made this query:

//first table
SELECT * FROM `books`

//join the junction 
LEFT JOIN books_authors ON books.book_id = books_authors.book_id

//join the authors
LEFT JOIN authors ON books_authors.author_id = authors.author_id

//limit to 8, start at S
limit S, 8

works fine when one-to-one. but when a book has more authors , like say 3 each, the sql result will have 8 x 3 rows in total (due to the 2D nature of the result) for all the details. but the query still clips it to 8 - i don't get all the details.

how to get 8 books with all details?

You could limit the number of books in a subquery:

select  * 
from    (
        select  *
        from    books
        limit   6, 7
        ) b
left join 
        ba ba
on      b.book_id = ba.book_id
left join 
        authors a
on      ba.author_id = a.author_id

Of the top of my head, I'd guess you could try something like

select * 
from ( select * from books limit s, 8 ) booksLimited
join books_authors on booksLimited.book_id = books_authors.book_id
join authors on books_authors.author_id = authors.book_id

But I'm not going to go to the effort of installing mySQL just to try this out for you. If it doesn't work, comment on it and I'll delete the answer.

Do not know what SQL features does your server support, but there are windowing functions that are supported by many. Essentially, you compute a sequential number to every book by given author in a particular ordering, and select only these having that number less or equal than 8 (for some value of 8). The numbering is provided by the function ROW_NUMBER():

SELECT * FROM (     
  SELECT a.author_id, b.book_id, a.name, b.title, 
         ROW_NUMBER() OVER (PARTITION BY a.author_id ORDER BY b.title) book_seq
    FROM author a 
    LEFT JOIN book b on a.author_id = b.author_id) dummy
  WHERE book_seq <= 8

Above, ORDER BY b.title defines the ordering in which you select the 8 minimal book records.

EDIT: mySQL does not support ROW_NUMBER(), so my answer does not apply as it is. There is an interesting article with examples on simulating ROW_NUMBER with OVER (PARTITION) in mySQL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM