web-dev-qa-db-ja.com

同じ列で複数のWHERE条件を使用した選択

わかりました、ここでは明白/単純なものを見落としているかもしれませんが、同じ列の複数の条件に一致するレコードのみを返すクエリを作成する必要があります...

私のテーブルは、ユーザーにフラグを適用するための非常にシンプルなリンク設定です...

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

など...この場合、連絡先99と100の両方に「ボランティア」と「アップロード済み」の両方のフラグが付けられます...

私ができる必要があるのは、検索フォームから入力された複数の条件に一致するcontactidのみを返すことです... contactidは選択したすべてのフラグに一致する必要があります...私の頭の中では、SQLは次のようになります

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

しかし...それは何も返しません...ここで何が間違っていますか?

62
RyanNehring

GROUP BYHAVING 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

contact_id, flagが一意であると仮定)。

または、結合を使用します。

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'

フラグのリストが非常に長く、多くの一致がある場合、最初のフラグがおそらくより高速です。フラグのリストが短く、一致するものが少ない場合は、おそらく2番目の方が速いことがわかります。パフォーマンスが懸念される場合は、データで両方をテストして、どちらが最適かを確認してください。

81
Mark Byers

つかいます:

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

重要なことは、t.flagのカウントはIN句の引数の数と等しくする必要があるということです。

COUNT(DISTINCT t.flag)の使用は、contactidとフラグの組み合わせに一意の制約がない場合です。重複する可能性がない場合は、クエリからDISTINCTを省略できます。

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

このようなINTERSECTの使用を検討してください。

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

それが最もロジスティックなソリューションだと思います。

9
wtct

テーブルは実際には見えませんが、フラグを「ボランティア」と「アップロード」の両方にすることはできません。列に複数の値がある場合、使用できます

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

書式設定されたテーブルを見ると実際には適用されません。

4
Orbit

この代替クエリを使用してみてください。

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