2010-02-20 24 views
6

Questa è la mia domanda:SQL: errore di sintassi con intersect?

-- 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"); 

Questo è l'errore:

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.

Che cosa sto facendo di sbagliato?

Questo è lo schema:

Fornitori (sid: interi, sname: stringa, stringa di indirizzo)

Parti (PID: interi, pname: stringa, colore: String)

catalogo (SID: integer, PID: integer, costo: vero e proprio)

grassetto = chiave primaria

risposta

6

MySQL, che sembrate essere utilizzato, non supporta la sintassi INTERSECT. Dovrai risolverlo in un altro modo.

In questo caso, è banale - abbiamo solo bisogno di un elenco di tutte le supplie che offrono "verde" e "rosso" di qualche parte - la tua query non si preoccupa di vedere se le parti stesse sono correlate, quindi possiamo risolverlo abbastanza facilmente in questo modo:

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 

Personalmente, non ritengo la query originale è un tipico INTERSECT problema. Date un'occhiata alla soluzione JOIN offerta da Vinko Vrsalovic per una soluzione generale per emulare il INTERSECT (che io preferirei btw anche se il RDBMS sarebbe infatti offerta INTERSECT nativamente)

+0

Sarebbe interessante vedere quale è più veloce, questa query o la mia query - penso che si riduca a che è più veloce, un 2 ° join o un gruppo per operazione. – Hogan

+0

@Hogan, * shrug *. Questo dipende da così tante cose: indici, quale motore, quante righe, quante memorie. elenco infinito ... se la domanda sarebbe stata quella di trovare la soluzione più veloce, avrei adottato un approccio completamente diverso per rispondere a questa domanda. Per ora, sono nella modalità di: come riscrivere SQL standard per ottenere un risultato equivalente nel caso in cui MySQL non accetti di supportare la sintassi. –

+0

punto preso, credo di essere sempre nella modalità di ciò che è più veloce, non è quello che è più chiaro. – Hogan

2

Questo dovrebbe fare quello che vuoi:

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

Non penso che questo sia il problema in questo caso. 'INTERSECT' semplicemente non è supportato da MySQL. –

+0

E quella query non funzionerà.L'OP vuole tutti i sids dove hanno una parte verde AND una rossa. La tua query restituisce tutti i sids con una parte OR verde o rossa. –

+0

@Roland, @Vinko: Sì, l'ho visto, ho aggiustato la risposta, questo dovrebbe fare ciò che vuole ed essere più veloce di una subquery. – Hogan

4

Niente, MySQL non ha la parola chiave INTERSECT . È possibile riscrivere come un 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); 

Questa query può sicuramente essere scritta meglio, ma questo è quello di mostrare che si intersecano è, ma semplicemente un inner join con un selezionato distinta, è possibile trasformare automaticamente l'uno nell'altro .

+0

Sono per lo più d'accordo, ma 'INTERSECT' non è esattamente uguale a' INNER JOIN'. 'INTERSECT' per default 'INTERSECT DISTINCT', che significa che è necessario restituire solo righe univoche. In casi pratici e probabilmente anche in questo caso, funzionerebbe, ma per ottenere una vera riscrittura, devi aggiungere "DISTINCT" o "GROUP BY' –

+0

@Roland: Grazie per la nota, ho modificato per rispecchiarlo . –

+0

tutto fantastico. Stai ottenendo +1 ora, perché fondamentalmente penso che "JOIN" sia molto, molto più bello di "INTERSECT" :) Solo il tempo che ho mai visto intersecato, è in compiti di lavoro in SQL;) –

0

Un'altra soluzione al fine di utilizzare INTERSECT in MySQL è quello di utilizzare IN clausola. Problema: "Trovare corso id di corsi offerti in autunno 2009 e Primavera 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’); 

In 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); 

Se avete bisogno di più sulle IN clausola, si prega di ricerca su Google .