1

I have three main tables: books, authors, publishers and two connecting tables: authors_on_books & books_on_publishers.

I'm trying to get all the data using the following query:

select books.*, 
        GROUP_CONCAT(authors.id) as author_id, GROUP_CONCAT(authors.name) as author_name,
        GROUP_CONCAT(publishers.id) as publisher_id, GROUP_CONCAT(publishers.name) as publisher_name

        from books
        join authors_on_books on authors_on_books.book_id = books.id
        join authors on authors_on_books.author_id = authors.id
        join books_on_publishers on books_on_publishers.book_id = books.id
        join publishers on books_on_publishers.publisher_id = publishers.id
        group by books.id

The result I'm getting is:

[id] => 1
[title] => Title 1
[description] => This is a book
[year_published] => 1999
[isbn] => 11111111
[author_id] => 1,1,2,2,3,3
[author_name] => author 1,author 1,author 2,author 2,author 3,author 3
[publisher_id] => 1,1,1,1,1,1
[publisher_name] => publisher 1,publisher 1,publisher 1,publisher 1,publisher 1,publisher 1

But the desired outcome is:

[id] => 1
[title] => Title 1
[description] => This is a book
[year_published] => 1999
[isbn] => 11111111
[author_id] => 1,2,3
[author_name] => author 1,author 2,author 3
[publisher_id] => 1,2
[publisher_name] => publisher 1,publisher 2

1 Answer 1

3

You should use distinct in group_concat

  select books.*, 
    GROUP_CONCAT(distinct uthors.id) as author_id, 
    GROUP_CONCAT(distinct authors.name) as author_name,
    GROUP_CONCAT(distinct publishers.id) as publisher_id, 
    GROUP_CONCAT(distinct publishers.name) as publisher_name

    from books
    join authors_on_books on authors_on_books.book_id = books.id
    join authors on authors_on_books.author_id = authors.id
    join books_on_publishers on books_on_publishers.book_id = books.id
    join publishers on books_on_publishers.book_id = publishers.id
    group by books.id

But remember that group_concat(distinct...) have a certain impact on performance..

and as suggested by gordon linoff you could use left join for ensure that get all books

  select books.*, 
    GROUP_CONCAT(distinct uthors.id) as author_id, 
    GROUP_CONCAT(distinct authors.name) as author_name,
    GROUP_CONCAT(distinct publishers.id) as publisher_id, 
    GROUP_CONCAT(distinct publishers.name) as publisher_name

    from books
    left join authors_on_books on authors_on_books.book_id = books.id
    left join authors on authors_on_books.author_id = authors.id
    left join books_on_publishers on books_on_publishers.book_id = books.id
    left join publishers on books_on_publishers.book_id = publishers.id
    group by books.id
Sign up to request clarification or add additional context in comments.

3 Comments

This is a fine solution, but I should note two things. First, you may want to use left joins to ensure that you get all books, even those with no authors or publishers in the database (if that is possible). Second, I note that pre-aggregating the authors and publishers may result in better performance.
@GordonLinoff thanks .. correct .. answer updated with your suggestion too
How can I fix the answer to display books with a specific author (together with co-authors)?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.