web-dev-qa-db-fra.com

SÉLECTION avec plusieurs conditions WHERE sur la même colonne

Ok, je pense que je peux oublier quelque chose d’évident/simple ici ... mais je dois écrire une requête qui ne renvoie que les enregistrements qui correspondent à plusieurs critères sur la même colonne ...

Ma table est une configuration de liaison très simple pour appliquer des drapeaux à un utilisateur ...

ID   contactid  flag        flag_type 
-----------------------------------
118  99         Volunteer   1 
119  99         Uploaded    2 
120  100        Via Import  3 
121  100        Volunteer   1  
122  100        Uploaded    2

etc ... dans ce cas, vous verrez que les contacts 99 et 100 sont marqués à la fois comme "Volontaire" et "Téléchargé" ...

Ce que je dois être capable de faire est de renvoyer UNIQUEMENT les identifiants de contact qui correspondent à plusieurs critères entrés via un formulaire de recherche ... les identifiants de contact doivent correspondre à TOUS les indicateurs choisis ... dans ma tête, le code SQL devrait ressembler à quelque chose comme:

SELECT contactid 
 WHERE flag = 'Volunteer' 
   AND flag = 'Uploaded'...

mais ... ça ne retourne rien ... Qu'est-ce que je fais mal ici?

62
RyanNehring

Vous pouvez soit utiliser GROUP BY et HAVING COUNT(*) = _:

SELECT contact_id
FROM your_table
WHERE flag IN ('Volunteer', 'Uploaded', ...)
GROUP BY contact_id
HAVING COUNT(*) = 2 -- // must match number in the WHERE flag IN (...) list

(en supposant que contact_id, flag est unique).

Ou utilisez des jointures:

SELECT T1.contact_id
FROM your_table T1
JOIN your_table T2 ON T1.contact_id = T2.contact_id AND T2.flag = 'Uploaded'
-- // more joins if necessary
WHERE T1.flag = 'Volunteer'

Si la liste des drapeaux est très longue et qu'il y a beaucoup de correspondances, le premier est probablement plus rapide. Si la liste des drapeaux est courte et qu'il y a peu de correspondances, vous constaterez probablement que la seconde est plus rapide. Si les performances sont un problème, essayez de tester les deux sur vos données pour voir celle qui fonctionne le mieux.

81
Mark Byers

Utilisation:

  SELECT t.contactid
    FROM YOUR_TABLE t
   WHERE flag IN ('Volunteer', 'Uploaded')
GROUP BY t.contactid
  HAVING COUNT(DISTINCT t.flag) = 2

L'important est que le comptage de t.flag doive être égal au nombre d'arguments de la clause IN.

L'utilisation de COUNT(DISTINCT t.flag) existe dans le cas où il n'y a pas de contrainte unique sur la combinaison de contactid et flag - s'il n'y a aucune chance de les dupliquer, vous pouvez omettre le DISTINCT de la requête:

  SELECT t.contactid
    FROM YOUR_TABLE t
   WHERE flag IN ('Volunteer', 'Uploaded')
GROUP BY t.contactid
  HAVING COUNT(t.flag) = 2
17
OMG Ponies

Pensez à utiliser INTERSECT comme ceci:

SELECT contactid WHERE flag = 'Volunteer' 
INTERSECT
SELECT contactid WHERE flag = 'Uploaded'

Je pense que c'est la solution la plus logistique.

9
wtct

ne peut pas vraiment voir votre table, mais flag ne peut pas être à la fois "volontaire" et "téléchargé". Si vous avez plusieurs valeurs dans une colonne, vous pouvez utiliser

WHERE flag LIKE "%Volunteer%" AND flag LIKE "%UPLOADED%"

pas vraiment applicable vu le tableau formaté.

4
Orbit

Essayez d'utiliser cette autre requête:

SELECT A.CONTACTID 
FROM (SELECT CONTACTID FROM TESTTBL WHERE FLAG = 'VOLUNTEER')A , 
(SELECT CONTACTID FROM TESTTBL WHERE FLAG = 'UPLOADED') B WHERE A.CONTACTID = B.CONTACTID;
3
Pankaj Singh