AUSWÄHLEN mit mehreren WHERE-Bedingungen in derselben Spalte


77

Ok, ich denke, ich übersehen hier möglicherweise etwas Offensichtliches / Einfaches ... aber ich muss eine Abfrage schreiben, die nur Datensätze zurückgibt, die mehreren Kriterien in derselben Spalte entsprechen ...

Meine Tabelle ist ein sehr einfaches Verknüpfungssetup zum Anwenden von Flags auf einen Benutzer ...

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 ... in diesem Fall sehen Sie, dass sowohl Kontakt 99 als auch 100 als "Freiwilliger" und "Hochgeladen" gekennzeichnet sind ...

Was ich tun muss, ist, NUR die Kontakt-IDs zurückzugeben, die mehreren Kriterien entsprechen, die über ein Suchformular eingegeben wurden. Die Kontakt-IDs müssen mit ALLEN ausgewählten Flags übereinstimmen. In meinem Kopf sollte die SQL ungefähr so ​​aussehen:

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

aber ... das bringt nichts zurück ... Was mache ich hier falsch?


2
Diese Anweisung funktioniert nicht, da das Flag nicht gleichzeitig mit "Volunteer" und "Upload" identisch sein kann. Sie können den Operator OR anstelle von AND verwenden, und es wird funktionieren.
Johar Zaman

Antworten:


96

Sie können entweder verwenden GROUP BYund 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

(vorausgesetzt, es contact_id, flagist einzigartig).

Oder verwenden Sie Joins:

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'

Wenn die Liste der Flags sehr lang ist und es viele Übereinstimmungen gibt, ist die erste wahrscheinlich schneller. Wenn die Liste der Flags kurz ist und es nur wenige Übereinstimmungen gibt, werden Sie wahrscheinlich feststellen, dass die zweite schneller ist. Wenn die Leistung ein Problem darstellt, testen Sie beide Daten, um festzustellen, welche am besten funktioniert.


1
Das Problem mit JOINs besteht darin, dass es Duplikate für die T1-Referenzen gibt, wenn mehr als ein Datensatz einer Kontakt-ID mit dem Flag "Hochgeladen" verknüpft ist.
OMG Ponys

SELECT contact_id FROM your_table WHERE (Flag IN ('Volunteer', 'Uploaded', ...) und one_type = sometype_one) UND flag IN ('someOtherVolunteer', 'Uploaded', ...) und second_type = sometype_two GROUP BY contact_id HAVING COUNT (*) = 2 Sir, ich habe das gleiche Szenario wie oben, aber es gibt null zurück. Null Zeilen.
Bangash

Im Falle einer Selbstverknüpfung benötigen Sie für N Werte eine Anzahl von N Selbstverknüpfungen. Was ist in diesem Beispiel, wenn Sie die Ergebnisse mit all diesen drei Flags "Hochgeladen", "Freiwillig" und "Über Import" erhalten müssen? Ich denke also, dass die Verwendung GROUP BYmit HAVING COUNTsinnvoller ist.
Sri

21

Verwenden:

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

Der Schlüssel ist, dass die Zählung t.flagder Anzahl der Argumente in der INKlausel entsprechen muss.

Die Verwendung von COUNT(DISTINCT t.flag)ist für den Fall, dass die Kombination von Kontakt-ID und Flag nicht eindeutig eingeschränkt ist. Wenn keine Duplikate möglich sind, können Sie das DISTINCT in der Abfrage weglassen:

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

10

Verwenden Sie INTERSECT wie folgt:

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

Ich denke, es ist die logistischste Lösung.


Da der Fragesteller mysql markiert hat, finde ich es gut, darauf hinzuweisen, dass INTERSECT für MySql nicht funktioniert
linkonabe

6

Ich kann Ihren Tisch nicht wirklich sehen, aber die Flagge kann nicht gleichzeitig "Freiwillig" und "Hochgeladen" sein. Wenn eine Spalte mehrere Werte enthält, können Sie diese verwenden

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

Nicht wirklich zutreffend, wenn man die formatierte Tabelle sieht.


3

Versuchen Sie, diese alternative Abfrage zu verwenden:

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;


-2

Ändern Sie AND in OR. Einfacher Fehler. Betrachten Sie es als einfaches Englisch, ich möchte alles auswählen, was diesem oder jenem entspricht.


-3

ANDSie erhalten nur dann eine Antwort, wenn beide volunteerund uploadedin Ihrer Spalte vorhanden sind. Andernfalls wird der nullWert zurückgegeben ...

versuchen Sie es ORin Ihrer Aussage ...

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

Dies zeigt alle Einträge, die VolunteerODER sind, Uploadedaber er möchte Einträge, die zweimal in sind und jeweils einmal haben
kero

-3
select purpose.pname,company.cname
from purpose
Inner Join company
on purpose.id=company.id
where pname='Fever' and cname='ABC' in (
  select mname
  from medication
  where mname like 'A%'
  order by mname
); 

-3

dein Code :

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

wird nicht funktionieren, da Sie den Tabellennamen nicht deklariert haben. Die Ausführung gibt eine Fehlermeldung zurück.

und wenn beide Suchabfragen angezeigt werden sollen, sollte Ihr Code ungefähr so ​​aussehen.

SELECT * FROM (your_table_name) WHERE flag = 'Volunteer' OR flag = 'Uploaded';

und nicht so, weil es immer false zurückgibt. SELECT * FROM (your_table_name) WHERE flag = 'Volunteer' AND flag = 'Uploaded';

Sie können dies auch tun

SELECT * FROM (your_table_name) 
WHERE flag = 'Volunteer' OR flag = 'Uploaded' 
ORDER BY contactid, flag asc; 

(Aufsteigend für aufsteigende Reihenfolge, Sie können es auch in absteigend ändern, wenn es in absteigender Reihenfolge angezeigt werden soll.)


-3

Verwenden Sie dies: Zum Beispiel:

select * from ACCOUNTS_DETAILS
where ACCOUNT_ID=1001
union
select * from ACCOUNTS_DETAILS
where ACCOUNT_ID=1002

-5

Manchmal kann man den Wald vor lauter Bäumen nicht sehen :)

Ihre ursprüngliche SQL ..

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

Sollte sein:

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

1
Ich glaube nicht, dass dies die gewünschten OP-Ergebnisse liefert. Die Kontakt-IDs müssen mit ALLEN Flags übereinstimmen, nicht mit einem oder mehreren.
Kildareflare
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.