2010-09-20 33 views
0

Situation: Tableau livre est associé à un ou plusieurs auteurs via le _author_book tableau. C'est également associé à un ou plusieurs genres via le _book_genre tableau.Est-il possible d'avoir plusieurs composite (alias « many-to-many », ManyToMany) les jointures qui ne font pas le jeu de résultats énorme

Lors de la sélection de tous les livres et tous les genres, et tous leurs auteurs, le nombre de lignes renvoyées est (en supposant chaque livre a au moins un genre et auteur):

  • PROBLÈME: livres. carte (| livre | book.genres.size * book.authors.size) .sum

ce que je veux est:

  • Souhaité: books.map (| livre | [Book.genres.size, book.authors.size] .max) .sum

donc donné 10 livres, chaque livre a 5 genres et 4 auteurs:

  • PROBLÈME: 200 lignes renvoyées (5 * 4 * 10)
  • souhaité: 50 lignes retournées ([5,4] * .max 10)

Exemple données:

 
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 

Voilà ce qui ne va pas:

 
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 

Espérons qu'il est clair que le problème est. Le résultat de la première jointure, le genre/_book_genre, est joint à tous les résultats de l'auteur, ce qui a resultset de 14 lignes, alors qu'en réalité un jeu de résultats de seulement sept lignes suffirait:

 
 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 

(en variante, les auteurs dupliqués pourraient être des valeurs NULL, mais s'il y a une réponse là-bas, je suppose que cela entraînera la répétition des auteurs comme ci-dessus).

Ma question: existe-t-il une combinaison de DÉMARRAGE DE SÉLECTION A, B, A, B, A, B, A, B, A, B, B, A, B, B, B, B, A et B?

Répondre

1

Grouper par et max est ce que vous voulez.

+0

Je ne vois pas comment le groupe par et/ou max va faire du bien ici. Qu'est-ce que je regroupe par ici? genre.id? perdre les auteurs. author.id? perdre les genres.max n'en renvoie qu'un seul dans un groupe, qui a déjà perdu des données. – colinta

+0

(de retour après le test) J'ai essayé un tas de combinaisons de GROUP BY, même jeté dans certains MAX(), bien que ce soit un demi-hearted je vais admettre. Je n'ai pas eu le "whif" de progrès ... – colinta

0

Votre deuxième jeu de résultats semble erroné:

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

peut signifier à peine ce que vous voulez. Essayez de formuler le résultat comme vous le voulez, et vous serez probablement capable de construire l'énoncé que vous recherchez. À moins que vous ne puissiez le dire correctement, les gens auront du mal à répondre à cette question, ou du moins je le ferai.

+0

J'ai vérifié deux fois, le libellé est correct (ou au moins approprié). J'ai trois groupes de données qui reviennent: les livres (2), les genres (4 sur le livre un, 3 sur le livre deux), et les auteurs (deux pour chaque livre) le jeu de résultats JE VEUX revenir (et ici mensonges ma question) ne contient que 7 lignes, et non 14. Considérons le cas où un élément a 20 "catégories" et 10 "genres" faisant deux jointures plusieurs-à-plusieurs entraînera 200 lignes. Y at-il une solution qui renvoie seulement 20 lignes (puisque c'est le minimum nécessaire pour afficher TOUTES les catégories, et les genres seraient répétés) – colinta

+0

Pour moi, le jeu de résultats ci-dessus signifie: Il y a un livre appelé Dune: The ..., qui est à propos de l'armée lorsqu'il est écrit par Brian Herbert, et est sur Sci-Fi lorsqu'il est écrit par Kevin J Anderson. Pourquoi les militaires sont-ils dans la même rangée que Brian Herbert et Sci-Fi dans la même rangée que Kevin J anderson? – Martijn

+0

Le but est d'avoir TOUTES les catégories et TOUS les auteurs, mais seulement retourner les lignes MAX (COUNT (auteurs), COUNT (catégories)). L'appariement ici est arbitraire et accessoire, pas une caractéristique désirée. – colinta