2010-02-20 29 views
6

Esta es mi consulta:SQL: ¿Error de sintaxis 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"); 

Este es el error:

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é estoy haciendo mal?

Este es el esquema:

Proveedores (sid: enteros, sname: de cadena, cadena de dirección)

Partes (pid: enteros, pname: cadena, color: String)

Catálogo (sid: entero, PID: número entero, costo: bienes)

= negrita clave primaria

Respuesta

6

MySQL, que parecen estar utilizando, no soporta la sintaxis INTERSECT. Tendrás que resolverlo de otra manera.

En este caso, es trivial, solo necesitamos una lista de todos los proveedores que ofrecen "verde" y "rojo" de alguna parte, su consulta no se preocupa de ver si las partes están relacionadas, entonces podemos resolverlo con bastante facilidad como esto:

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, no creo que la consulta original es un problema típico INTERSECT. Echar un vistazo a la solución ofrecida por JOIN Vinko Vrsalovic para una solución general para emular el INTERSECT (que por cierto yo preferiría incluso si el RDBMS sería en oferta INTERSECT hecho de forma nativa)

+0

Sería interesante ver cuál es más rápido, esta consulta o mi consulta: creo que todo se reduce a lo que es más rápido, una segunda unión o un grupo por operación. – Hogan

+0

@Hogan, * encogimiento de hombros *. Esto depende de muchas cosas: índices, qué motor, cuántas filas, cuánta memoria. lista inútil ... si la pregunta hubiera sido encontrar la solución más rápida, habría tomado un enfoque completamente diferente para responder a esto. Por ahora, estoy en el modo de: cómo reescribir SQL estándar para obtener un resultado equivalente en caso de que MySQL no soporte la sintaxis. –

+0

punto tomado, supongo que siempre estoy en el modo de lo que es más rápido, no lo que es más claro. – Hogan

2

Esto debería hacer lo que quiera:

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

No creo que ese sea el problema en este caso. 'INTERSECT' simplemente no es compatible con MySQL. –

+0

Y esa consulta no funcionará.El OP quiere que todos los sids tengan una parte verde Y otra roja. Su consulta devuelve todos los sids con una parte verde o una roja. –

+0

@Roland, @Vinko: Sí, lo vi, arreglé la respuesta, esto debería hacer lo que él quiere y ser más rápido que una subconsulta. – Hogan

4

Nada, MySQL no tienen la palabra clave INTERSECT . Puede volver a escribir como 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); 

Esta consulta puede sin duda ser mejor escrito, pero esto es para demostrar que se cruzan no es más que unirse simplemente un interior con un selecto distinta, puede transformar de forma automática una en la otra .

+0

Estoy de acuerdo, pero 'INTERSECT' no es exactamente lo mismo que' INNER JOIN'. 'INTERSECT' se establece por defecto en' INTERSECT DISTINCT', lo que significa que es necesario devolver solo filas únicas. En casos prácticos y probablemente también en este caso, simplemente funcionaría, pero para obtener una verdadera reescritura, tendría que agregar 'DISTINCT' o' GROUP BY' –

+0

@Roland: gracias por la nota, la edité para reflejarla . –

+0

todo genial. Estás obteniendo +1 ahora, porque básicamente creo que 'JOIN' es mucho, mucho mejor que' INTERSECT' :) La única vez que vi corte, es en SQL tareas asignadas;) –

0

Otra solución con el fin de utilizar INTERSECT en MySQL es utilizar EN cláusula. Problema: "Find ID del curso de los cursos que se ofrecen en el otoño de 2009 y la primavera de 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’); 

En 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 necesitas más en EN cláusula, por favor buscar en Google .