2010-02-19 5 views
27

J'ai deux tables, enregistrements et données. les enregistrements ont plusieurs champs (prénom, nom, etc.). Chacun de ces champs est une clé étrangère pour la table de données où la valeur réelle est stockée. J'ai besoin de chercher sur plusieurs champs d'enregistrement. Ci-dessous un exemple de requête utilisant INTERSECT, mais j'en ai besoin d'un qui fonctionne dans MySQL.INTERSECT dans 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" 

Merci pour toute aide.

+1

Jetez un oeil à ceci: http://www.codinghorror.com/ blog/2007/10/a-visual-explication-de-sql-joins.html –

+0

@Mike Atlas: Cela n'a rien à voir avec les jointures. Cela peut être résolu de cette façon, mais l'article de Jeff n'est pas pertinent. – Aaronaught

+1

Oui, cela concerne les jointures et est pertinent. Il explique quelle jointure SQL est équivalente à une intersection de deux données (jointure interne). À partir de là, Jeremy devrait être capable de comprendre la syntaxe SQL standard pour "intersection". J'ai seulement posté ceci comme commentaire puisque d'autres ont donné la réponse exacte ci-dessous. –

Répondre

23

Vous pouvez utiliser une jointure interne pour filtrer les lignes qui ont une ligne correspondante dans une autre table:

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" 

L'une des nombreuses autres alternatives est une clause in:

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

J'aime l'idée de la clause «WHERE» le meilleur – scottyseus

5

utilisation rejoint la place :

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' 

Voici quelques données de test:

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

Résultat attendu:

2 

Les données de test est probablement pas utile pour l'affiche, mais peut être utile pour les électeurs qui veulent vérifier des solutions pour voir qu'ils fonctionnent correctement, ou les personnes qui veulent soumettre des réponses afin qu'ils puissent tester leurs propres réponses.

8

Je pense que cette méthode est beaucoup plus facile à suivre, mais il y a un peu d'une surcharge associée à parce que vous chargez des tas de dossiers en double au départ. Je l'utilise sur une base de données avec environ 10000-50000 enregistrements et généralement croiser environ 5 requêtes et la performance est acceptable.

Tout ce que vous faites est « UNION ALL » chacune des requêtes que vous souhaitez recouper et voir ceux qui vous avez à chaque fois.

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 

Donc, si nous obtenons le même enregistrement dans les deux requêtes, il est chef d'accusation sera 2 et l'enveloppe autour de requête finale inclure.

0

Un remplaçant pour INTERSECT dans MYSQL est jointure interne:

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) 

Ou pour votre cas particulier:

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)