2008-11-06 6 views
1

J'ai deux tables que je voudrais joindre mais je reçois une erreur de MySQLrequête: produit croisé au lieu de rejoindre

Table: books 
bookTagNum ShelfTagNum 
book1  1 
book2  2 
book3  2 

Table: shelf 
shelfNum shelfTagNum 
1   shelf1 
2   shelf2 

Je veux que mes résultats soient:

bookTagNum ShelfTagNum shelfNum 
book1  shelf1   1 
book2  shelf2   2 
book3  shelf2   2 

mais à la place, je suis également obtenir un résultat supplémentaire:

book1  shelf2   2 

Je pense que ma requête est en train de faire un produit croisé au lieu d'une jointure:

SELECT `books`.`bookTagNum` , `books`.`shelfNum` , `shelf`.`shelfTagNum` , `books`.`title` 
FROM books, shelf 
where `books`.`shelfNum`=`books`.`shelfNum` 
ORDER BY `shelf`.`shelfTagNum` ASC 
LIMIT 0 , 30 

Qu'est-ce que je fais mal?

+0

Note: J'ai essayé de répondre du mieux que je peux, mais votre question est un peu déroutante, puisque votre exemple n'affiche pas de colonnes books.shelfNum ou books.title, même si vous les référencez dans votre requête. Et votre sortie a 3 colonnes même si vous avez demandé 4. –

+0

Les jointures IMplicit sont une pratique de programmation très pauvre. Ils sont sujets à des jointures accidentelles et beaucoup plus difficiles à maintenir (par exemple, était-ce une jointure délibérée ou un bug?) Ils sont dépassés depuis 1992 et il n'y a aucune excuse pour en utiliser un quand un meilleur, plus desciptif, L'option moins ouverte aux bogues est disponible. – HLGEM

Répondre

8

Je pense que vous voulez

where `books`.`shelfTagNum`=`shelf`.`shelfNum` 

Afin de faire correspondre les lignes des tables books et shelf, vous devez avoir des termes de chacun dans votre where clause - sinon, vous êtes juste d'effectuer une opération sans vérifiez sur les lignes de books, car shelfNum sera égal à shelfNum. Comme le suggère @ fixme.myopenid.com, vous pouvez également utiliser la route explicite JOIN, mais ce n'est pas nécessaire.

+0

Je pense qu'il veut books.shelfNum = shelf.shelfTagNum –

0

Essayez ceci:

SELECT `books`.`bookTagNum` , `books`.`shelfNum` , `shelf`.`shelfTagNum` , 
    `books`.`title` 
FROM books, shelf 
where `books`.`shelftagNum`=`shelf`.`shelfNum` 
ORDER BY `shelf`.`shelfTagNum` ASC 
LIMIT 0 , 30 

Parce que la condition de jointure implicite n'a pas été correctement déclaré le résultat était un produit croisé.

1

Vérifiez votre SQL. Votre clause where ne peut pas être books. shelfNum = books. shelfNum

Et à quoi servent toutes ces guillemets simples?

+0

Les guillemets sont le format de citation de mot-clé pour mysql ... – Stobor

5

si vous voulez être sûr que vous faites une jointure au lieu d'un produit croisé, vous devez indiquer explicitement dans le SQL, ainsi:

SELECT books.bookTagNum,books.shelfNum, shelf.shelfTagNum, books.title 
FROM books INNER JOIN shelf ON books.shelfNum = shelf.shelfTagNum 
ORDER BY shelf.shelfTagNum 

(qui renverra uniquement les lignes qui existent dans les deux tables), ou:

SELECT books.bookTagNum,books.shelfNum, shelf.shelfTagNum, books.title 
FROM books LEFT OUTER JOIN shelf ON books.shelfNum = shelf.shelfTagNum 
ORDER BY shelf.shelfTagNum 

(qui renverra toutes les lignes de livres), ou:

SELECT books.bookTagNum,books.shelfNum, shelf.shelfTagNum, books.title 
FROM books RIGHT OUTER JOIN shelf ON books.shelfNum = shelf.shelfTagNum 
ORDER BY shelf.shelfTagNum 

(qui wil l retourner toutes les rangées de l'étagère)

+0

@fixme: la notation que Steve a employée est parfaitement acceptable aux programmeurs de SQL old-school, même si ce que vous suggérez est préféré . Cela fonctionne correctement aussi. –

+0

@Jonathan Leffler, La syntaxe de la jointure implicite est très imparfaite et ne devrait être acceptable pour aucun programmeur professionnel. – HLGEM

4

FYI: Si vous réécrivez vos noms pour être cohérent, les choses deviennent beaucoup plus faciles à lire.

Table 1: Book 
BookID  ShelfID BookName 
1   1  book1 
2   2  book2 
3   2  book3 

Table 2: Shelf 
ShelfID ShelfName 
1   shelf1 
2   shelf2 

maintenant, une requête pour extraire des livres à étagères est

SELECT 
b.BookName, 
s.ShelfName 
FROM 
Book b 
JOIN Shelf s ON s.ShelfID = b.ShelfID 

Pour répondre à la question initiale:

> where `books`.`shelfNum`=`books`.`shelfNum` 
>  ^^^^^--------------^^^^^------------- books repeated - this is an error 

la clause WHERE, comme il est écrit, ne fait rien, et parce que votre clause where ne limite aucune ligne, vous obtenez en effet le produit croisé.

0

Comme d'autres l'ont mentionné, le problème que vous avez rencontré était avec votre condition ON. Pour répondre spécifiquement à votre question:

En MySQL, si vous omettez un JOIN, un INNER JOIN/CROSS JOIN est utilisé. Pour les autres bases de données, c'est différent. Par exemple, PostgreSQL utilise un CROSS JOIN, pas un INNER JOIN.

Re: http://dev.mysql.com/doc/refman/5.7/en/join.html

« En MySQL, JOIN, CROSS JOIN et INNER JOIN sont équivalents syntaxiques (ils peuvent remplacer l'autre) dans le standard SQL, ils ne sont pas équivalents INNER JOIN est utilisé avec un ON.. clause, CROSS JOIN est utilisée autrement. "

Questions connexes