2010-02-19 15 views
27

Tengo dos tablas, registros y datos. registros tiene múltiples campos (nombre, apellido, etc.). Cada uno de estos campos es una clave externa para la tabla de datos donde se almacena el valor real. Necesito buscar en múltiples campos de registro.INTERSECT en MySQL

A continuación se muestra una consulta de ejemplo usando INTERSECT, pero necesito una que funcione en MySQL.

SELECT records.id FROM records, data WHERE data.id = records.firstname AND data.value = "john" 
INTERSECT 
SELECT records.id FROM records, data WHERE data.id = records.lastname AND data.value = "smith" 

Gracias por cualquier ayuda.

+1

Tener un vistazo a esto: http://www.codinghorror.com/ blog/2007/10/a-visual-explanation-of-sql-joins.html –

+0

@Mike Atlas: Esto no tiene nada que ver con las uniones. Se puede resolver de esa manera, pero la publicación de Jeff no es relevante. – Aaronaught

+1

Sí, tiene que ver con uniones, y es relevante. Explica qué combinación de SQL es equivalente a una intersección de dos datos (unión interna). A partir de esto, Jeremy debería poder descifrar la sintaxis SQL estándar para "intersección". Solo publiqué esto como un comentario, ya que otros dieron la respuesta exacta a continuación. –

Respuesta

23

Puede utilizar una combinación interna para filtrar las filas que tienen una fila coincidente en otra tabla:

SELECT DISTINCT records.id 
FROM records 
INNER JOIN data d1 on d1.id = records.firstname AND data.value = "john" 
INNER JOIN data d2 on d2.id = records.lastname AND data.value = "smith" 

Una de muchas otras alternativas es un in cláusula:

SELECT DISTINCT records.id 
FROM records 
WHERE records.firstname IN (
    select id from data where value = 'john' 
) AND records.lastname IN (
    select id from data where value = 'smith' 
) 
+1

Me gusta la idea de la cláusula 'WHERE' la mejor – scottyseus

5

Uso une vez :

SELECT records.id 
FROM records 
JOIN data AS D1 ON records.firstname = D1.id 
JOIN data AS D2 ON records.lastname = D2.id 
WHERE D1.value = 'john' and D2.value = 'smith' 

Aquí hay algunos datos de prueba:

CREATE TABLE records (id INT NOT NULL, firstname INT NOT NULL, lastname INT NOT NULL); 
INSERT INTO records (id, firstname, lastname) VALUES 
(1, 1, 1), 
(2, 1, 2), 
(3, 2, 1), 
(4, 2, 2); 

CREATE TABLE data (id INT NOT NULL, value NVARCHAR(100) NOT NULL); 
INSERT INTO data (id, value) VALUES 
(1, 'john'), 
(2, 'smith'); 

Resultado esperado:

2 

Los datos de prueba no es probablemente útil para el cartel, pero podría ser útil para los votantes que quieren revisar soluciones para ver que funcionan correctamente, o la gente que quiere envíe respuestas para que puedan probar sus propias respuestas.

8

Creo que este método es mucho más fácil de seguir, pero hay un poco de sobrecarga asociada porque carga muchos registros duplicados inicialmente. Lo uso en una base de datos con aproximadamente 10000-50000 registros y generalmente se cruzan alrededor de 5 consultas y el rendimiento es aceptable.

Todo lo que debes hacer es "UNION TODO", cada una de las consultas que deseas cruzarte y ver cuáles obtienes cada vez.

SELECT * From (

    (Select data1.* From data1 Inner Join data2 on data1.id=data2.id where data2.something=true) 
    Union All 
    (Select data1.* From data1 Inner Join data3 on data1.id=data3.id where data3.something=false) 

) As tbl GROUP BY tbl.ID HAVING COUNT(*)=2 

Así que si conseguimos el mismo registro en ambas consultas, es el recuento será 2 y la envolvente de la última consulta lo incluirá.

0

un reemplazo general de INTERSECT en MySQL es combinación interna:

SELECT DISTINCT * FROM 
(SELECT f1, f2, f3... FROM table1 WHERE f1>0) 
INNER JOIN 
(SELECT f1, f2, f3... FROM table2 WHERE f1>0) 
USING(primary_key) 

O para su caso concreto:

SELECT DISTINCT * FROM 
(SELECT records.id FROM records, data WHERE data.id = records.firstname AND data.value = "john") query1 
INNER JOIN 
(SELECT records.id FROM records, data WHERE data.id = records.lastname AND data.value = "smith") query2 
USING (id)