2010-02-20 4 views
6

C'est ma requête:SQL: Erreur de syntaxe avec Intersection?

-- Sids of suppliers who supply a green part AND a red part 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "red") 
INTERSECT 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "green"); 

Ceci est l'erreur:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "INTERSECT (SELECT Suppliers.sid FROM Suppliers JOIN Catalog ON Catalog.sid = Sup" on line 6.

Qu'est-ce que je fais mal?

C'est le schéma:

Fournisseurs (sid: entiers, sname: string, chaîne d'adresse)

Pièces (pid: entiers, pname: string, couleur: string)

Catalogue (sid: entier, pid: entier, coût: réel)

gras = clé primaire

Répondre

6

MySQL, que vous semblez utiliser, ne prend pas en charge la syntaxe INTERSECT. Vous allez devoir résoudre une autre façon.

Dans ce cas, il est trivial - nous avons seulement besoin d'une liste de tous les suppiers qui offrent "vert" et "rouge" d'une partie - votre requête ne dérange pas de voir si les parties elles-mêmes sont liées, nous pouvons résoudre assez facilement comme ceci:

SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color IN ('red', 'green') 
GROUP BY Suppliers.sid 
HAVING COUNT(DISTINCT Parts.color) = 2 

Personnellement, je ne crois pas que la requête initiale est un problème INTERSECT typique. Jetez un oeil à la solution REJOIGNEZ offerte par Vinko Vrsalovic pour une solution générale à imiter le INTERSECT (que je BTW préfère même si le SGBDR serait dans l'offre de fait INTERSECT nativement)

+0

Il serait intéressant de voir ce qui est le plus rapide, cette requête ou ma requête - je pense qu'il s'agit de savoir qui est le plus rapide, une deuxième jointure ou un groupe par opération. – Hogan

+0

@Hogan, * hausser les épaules *. Cela dépend de tant de choses: les index, le moteur, le nombre de lignes, le nombre de mémoires. enless list ... si la question avait été de trouver la solution la plus rapide, j'aurais adopté une approche totalement différente pour y répondre. Pour l'instant, je suis dans le mode de: comment réécrire le SQL standard pour obtenir un résultat équivalent au cas où MySQL n'arriverait pas à supporter la syntaxe. –

+0

point pris, je suppose que je suis toujours dans le mode de ce qui est le plus rapide, pas ce qui est le plus clair. – Hogan

2

Cela devrait faire ce que vous voulez:

SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
INNER JOIN Parts AS parts1 ON parts1.pid = Catalog.pid AND parts1.color = "red" 
INNER JOIN Parts AS parts2 ON parts2.pid = Catalog.pid AND parts2.color = "green" 
+0

Je ne pense pas que ce soit le problème dans ce cas. 'INTERSECT' est tout simplement pas pris en charge par MySQL. –

+0

Et cette requête ne fonctionnera pas.L'OP veut tous les SID où ils ont une partie verte et une partie rouge. Votre requête renvoie tous les SID avec une partie verte OU une partie rouge. –

+0

@Roland, @Vinko: Oui, j'ai vu ça, j'ai corrigé la réponse, cela devrait faire ce qu'il veut et être plus rapide qu'une sous-requête. – Hogan

4

Rien, MySQL n'a pas le mot-clé INTERSECT . Vous pouvez le réécrire comme INNER JOIN:

SELECT DISTINCT sid FROM 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "red") a 
INNER JOIN 
(SELECT Suppliers.sid 
FROM Suppliers 
JOIN Catalog ON Catalog.sid = Suppliers.sid 
JOIN Parts ON Parts.pid = Catalog.pid 
WHERE Parts.color = "green") b 
ON (a.sid = b.sid); 

Cette requête peut certainement être mieux écrit, mais cela est de montrer que Intersection est, mais simplement une jointure avec une sélection distincte, vous pouvez automatiquement transformer l'une en l'autre .

+0

Je suis plutôt d'accord, mais 'INTERSECT' n'est pas exactement le même que 'INNER JOIN'. 'INTERSECT' par défaut' INTERSECT DISTINCT', ce qui signifie qu'il est nécessaire de retourner uniquement des lignes uniques. Dans les cas pratiques et probablement dans ce cas aussi, cela fonctionnera, mais pour obtenir une réécriture, vous devrez ajouter "DISTINCT" ou "GROUP BY" –

+0

@Roland: Merci pour la note, j'ai édité pour la refléter . –

+0

tous frais. Vous obtenez +1 maintenant, parce que je pense fondamentalement 'JOIN 'est beaucoup, beaucoup plus agréable que' INTERSECT' :) Seul le temps que j'ai jamais vu se croiser, est dans les devoirs SQL;) –

0

Une autre solution pour utiliser INTERSECT dans MySQL est d'utiliser la clause IN. Problème: "Trouver id cours de des cours offerts à l'automne 2009 et printemps 2010"

//DML sample 
(select course_id 
from section 
where semester = ‘Fall’ and year = ‘2009’) 
intersect 
(select course_id 
from section 
where semester = ‘Spring’ and year = ‘2010’); 

MySQL:

select distinct course_id 
from section 
where semester = 'Fall' and year= 2009 and 
course_id in (select course_id 
from section 
where semester = 'Spring' and year= 2010); 

Si vous avez besoin sur IN clause, s'il vous plaît une recherche sur Google .