Можно ли иметь несколько составных (иначе называемых «многие ко многим», ManyToMany) соединений, которые не делают набор результатов огромным - PullRequest
0 голосов
/ 20 сентября 2010

Положение: Таблица книга связана с одним или несколькими авторами через таблицу _author_book . также связано с одним или несколькими жанрами через таблицу _book_genre .

При выборе всех книг, всех их жанров и всех их авторов возвращается количество строк (предположим, что каждая книга имеет по крайней мере один жанр и автора):

  • ПРОБЛЕМА: books.map (| book | book.genres.size * book.authors.size) .sum

что я хочу это:

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

так, учитывая 10 книг, каждая книга имеет 5 жанров и 4 автора:

  • ПРОБЛЕМА: возвращено 200 строк (5 * 4 * 10)
  • DESIRED: возвращено 50 строк ([5,4] .max * 10)

Пример данных:

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

Вот что не так:

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

Надеюсь, понятно, в чем проблема. Результат первого объединения в жанре / _book_genre объединяется со всеми результатами автора, в результате получается набор из 14 строк, тогда как на самом деле достаточно набора результатов, состоящего только из семи строк:

 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

(альтернативно, дублирующиеся авторы могут иметь значения NULL, но если есть ответ, я предполагаю, что это приведет к повторению авторов, как указано выше).

Мой вопрос: существует ли какая-либо комбинация ВЫБЕРИТЕ СТАРТ ВЛЕВО, ВПРАВО, ВНУТРЕННИЙ, ВНЕШНИЙ, А-Б-А-Б, которая не позволит многим-многим результатам умножить количество строк?

Ответы [ 2 ]

1 голос
/ 20 сентября 2010

Группировка по и максимум, что вы хотите.

0 голосов
/ 20 сентября 2010

Ваш второй набор результатов кажется неправильным:

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

Вряд ли может означать, что вы хотите.Попробуйте сформулировать набор результатов так, как вы этого хотите, и вы, вероятно, сможете составить искомое утверждение.Если вы не скажете это правильно, людям будет сложно ответить на этот вопрос, или, по крайней мере, я отвечу.

...