0

Situation: Table book is associated with one or more authors via the _author_book table. It is also associated with one or more genres via the _book_genre table.

When selecting all the books, and all their genres, and all their authors, the number of rows returned is (assume each book has at least one genre and author):

  • PROBLEM: books.map( |book| book.genres.size * book.authors.size).sum

what I want is:

  • DESIRED: books.map( |book| [book.genres.size, book.authors.size].max).sum

so given 10 books, each book has 5 genres and 4 authors:

  • PROBLEM: 200 rows returned (5 * 4 * 10)
  • DESIRED: 50 rows returned ( [5,4].max * 10 )

Example Data:

mysql> SELECT * FROM book

 id | title
----+---------------------------
 1  | Dune: The Butlerian Jihad
 2  | The Talisman

mysql> SELECT * FROM genre

 id | title
----+-------------
 1  | Military
 2  | Horror
 3  | Thriller
 4  | Sci-Fi
 5  | Fiction
 6  | Speculative

mysql> SELECT * FROM author

 id | title
----+------------------
 1  | Brian Herbert
 2  | Kevin J Anderson
 3  | Stephen King
 4  | Peter Straub

mysql> SELECT * FROM _author_book

 book_id | author_id
---------+-----------
 1       | 1
 1       | 2
 2       | 3
 2       | 4

mysql> SELECT * FROM _book_genre

 book_id | genre_id
---------+-----------
 1       | 1
 1       | 4
 1       | 5
 1       | 6
 2       | 2
 2       | 3
 2       | 5

Here's what's wrong:

mysql> SELECT book.id AS "book.id", ..., author.fullname AS "author.fullname" FROM book
    -> LEFT JOIN _book_genre ON book.id = _book_genre.book_id
    -> LEFT JOIN genre ON genre.id = _book_genre.genre_id
    -> LEFT JOIN _author_book ON book.id = _author_book.book_id
    -> LEFT JOIN author ON author.id = _author_book.author_id;

 book.id | book.title | genre.id | genre.name  | author.id | author.fullname
---------+------------+----------+-------------+-----------+------------------
 1       | Dune: The… | 1        | Military    | 1         | Brian Herbert
 1       | Dune: The… | 4        | Sci-Fi      | 1         | Brian Herbert
 1       | Dune: The… | 5        | Fiction     | 1         | Brian Herbert
 1       | Dune: The… | 6        | Speculative | 1         | Brian Herbert
---------+------------+----------+-------------+-----------+------------------
 1       | Dune: The… | 1        | Military    | 2         | Kevin J Anderson
 1       | Dune: The… | 4        | Sci-Fi      | 2         | Kevin J Anderson
 1       | Dune: The… | 5        | Fiction     | 2         | Kevin J Anderson
 1       | Dune: The… | 6        | Speculative | 2         | Kevin J Anderson
---------+------------+----------+-------------+-----------+------------------
 2       | The Talis… | 2        | Horror      | 3         | Stephen King
 2       | The Talis… | 3        | Thriller    | 3         | Stephen King
 2       | The Talis… | 5        | Fiction     | 3         | Stephen King
---------+------------+----------+-------------+-----------+------------------
 2       | The Talis… | 2        | Horror      | 4         | Peter Straub
 2       | The Talis… | 3        | Thriller    | 4         | Peter Straub
 2       | The Talis… | 5        | Fiction     | 4         | Peter Straub

Hopefully it is clear what the problem is. The result of the first join, on genre/_book_genre, is being joined with all the author results, resulting in a resultset of 14 rows, when really a result set of only seven rows would suffice:

 book.id | book.title | genre.id | genre.name  | author.id | author.fullname
---------+------------+----------+-------------+-----------+------------------
 1       | Dune: The… | 1        | Military    | 1         | Brian Herbert
 1       | Dune: The… | 4        | Sci-Fi      | 2         | Kevin J Anderson
 1       | Dune: The… | 5        | Fiction     | 1         | Brian Herbert
 1       | Dune: The… | 6        | Speculative | 2         | Kevin J Anderson
---------+------------+----------+-------------+-----------+------------------
 2       | The Talis… | 2        | Horror      | 3         | Stephen King
 2       | The Talis… | 3        | Thriller    | 4         | Peter Straub
 2       | The Talis… | 5        | Fiction     | 3         | Stephen King

(alternatively, the duplicated authors could be NULL values, but if there IS an answer out there, I am assuming it will result in the authors being repeated as above).

My Question: is there some combination of LEFT, RIGHT, INNER, OUTER, A-B-A-B SELECT START that will prevent the many-to-many results from multiplying the number of rows?

4

2 回答 2

1

Group by 和 max 是你想要的。

于 2010-09-20T18:07:50.977 回答
0

您的第二个结果集似乎错误:

1       | Dune: The… | 1        | Military    | 1         | Brian Herbert
1       | Dune: The… | 4        | Sci-Fi      | 2         | Kevin J Anderson

很难说你想要什么。试着用你想要的方式对结果集进行措辞,你可能能够构建你正在寻找的语句。除非你能恰当地用词,否则人们将很难回答这个问题,或者至少我会。

于 2010-09-20T18:15:21.637 回答