Question

J'ai plusieurs tables d'index et je souhaite effectuer une requête de type inclusion / exclusion.

fid est vraiment un index entier, mais ici sous forme de lettres pour en faciliter la compréhension. Voici un exemple de tableau:

table t

eid | fid
----+----
1   | A
1   | B
1   | C
2   | B
2   | C
3   | A
3   | C
4   | A
4   | B
5   | B

Voici quelques exemples de requêtes que je souhaite.

  1. Quels sont les eids fid B et PAS A? (Réponses 2 et 5)
  2. Quels eids ont fid C et PAS A? (Réponse eid 2)

Je n'arrive pas à trouver une requête qui le fasse.

J'ai essayé une auto-jointure comme ceci:

select * 
from t as t1 
join t as t2 
where t1.eid=t2.eid 
  and t1.fid!=t2.fid 
  and t1.fid=B and t2.fid!=A

Cela ne fonctionnera pas car il renverra toujours les lignes où eid = 1 et fid = C.

Suis-je clair sur ce que je veux?

Était-ce utile?

La solution

Voici un exemple de requête pour 1 (2 fonctionne à peu près de la même manière)

select t1.eid
  from t t1
 where t1.fid  = 'B'
   and not exists
       (select 1
          from t t2
         where t2.eid = t1.eid
           and t2.fid  = 'A')

Autres conseils

Utilisez définir la soustraction

.
Select eid from t where fid = 'B' 
EXCEPT
select eid from t where fid = 'A'

Vous pouvez utiliser une sous-sélection

sélectionnez eid de t où fid = 'C' et eid not in (sélectionnez eid de t où fid = 'A')

MySQL 5.0 soutient le où existe / existe pas, comme décrit par Nigel et Mike.

Version avec des jointures droites qui peuvent être plus rapides qu'avec EXISTS:

Select  t1.eid
From    #test t1
        left join (
            Select  eid
            From    #test t2 
            Where   fid = 'A'
            Group by eid
        ) t2 on t2.eid = t1.eid 
Where   t1.fid = 'B'
        and t2.eid is null

Cela devrait être possible sans utiliser de sous-requête:

SELECT DISTINCT t1.eid
FROM table1 AS t1
  LEFT JOIN table1 AS t2 ON (t1.eid = t2.eid AND t2.fid = 'A')
WHERE t2.eid IS NULL
  AND t1.fid = 'B';

Pour effectuer votre deuxième exemple de recherche, modifiez simplement la valeur "B" en "C".

Regardez dans l'opérateur MINUS. Cela fonctionne comme UNION, sauf qu’il soustrait l’ajout de UNION. La réponse précédente avec le mot "EXCEPT" peut être un mot clé différent pour la même chose.

Voici une réponse non testée:

select eid 
from t
where fid = 'A'
minus
select eid
from t
where fid = 'B'
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top