仅在匹配所有列表值时返回行

REA*_*O G 2 sql where

假设我有一张桌子customers:

-----------------
|id|name|country|
|1 |Joe |Mexico |
|2 |Mary|USA |
|3 |Jim |France |
-----------------

还有一张桌子languages:

-------------
|id|language|
|1 |English |
|2 |Spanish |
|3 |French |
-------------

还有一张桌子cust_lang:

------------------
|id|custId|langId|
|1 |1 |1 |
|2 |1 |2 |
|3 |2 |1 |
|4 |3 |3 |
------------------

给出一个列表:["英语","西班牙语","葡萄牙语"]使用a WHERE IN列表,它仍将返回带有ID 1,2的客户,因为它们匹配"英语"和"西班牙语".但是,结果应该返回0行,因为没有客户匹配所有三个术语.我只希望客户ID与cust_lang表匹配时返回.例如,给定一个列表:["英语","西班牙语"]我希望结果是客户Id 1,因为他一个人说两种语言.

编辑:@GordonLinoff - 有效!!

现在为了使它更复杂,这个额外的相关查询出了什么问题:

我们假设我也有一张桌子degrees:

-----------
|id|degree|
|1 |PHD |
|2 |BA |
|3 |MD |
-----------

相应的连接表cust_deg:

------------------
|id|custId|degId |
|1 |1 |1 |
|2 |1 |2 |
|3 |2 |1 |
|4 |3 |3 |
------------------

以下查询不起作用.但是,它是两个相同的查询组合.结果应该只是与两个列表匹配的行,而不是一个列表.

SELECT * FROM customers C
    WHERE C.id IN (
    SELECT CL.langId FROM cust_lang CL
    JOIN languages L on CL.langId = L.id 
    WHERE L.language IN ("English", "Spanish")
    GROUP BY CL.langID 
    HAVING COUNT(*) = 2) 
AND C.id IN (
        SELECT CD.custId FROM cust_deg CD
        JOIN degrees D ON CD.degID = D.id 
        WHERE D.degree IN ("PHD", "BA") 
        GROUP BY CD.custId HAVING COUNT(*) = 2));`
Run Code Online (Sandbox Code Playgroud)

EDIT2:我想我修好了.我不小心在那里有一个额外的选择声明.

Gor*_*off 5

你可以用group byhaving:

select cl.custid
from cust_lang cl join
     languages l
     on cl.langid = l.id
where l.language in ('English', 'Spanish', 'Portuguese')
group by cl.custid
having count(*) = 3;
Run Code Online (Sandbox Code Playgroud)

例如,如果您只想检查两种语言,那么您只需要更改您WHERE ... INHAVING条件,例如:

where l.language in ('English', 'Spanish')
Run Code Online (Sandbox Code Playgroud)

having count(*) = 2
Run Code Online (Sandbox Code Playgroud)