2016-07-01 44 views
1

比方說,我有一個表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 |
------------------

給出一個列表: 「英語」, 「西班牙」, 「葡萄牙」] 使用WHERE IN的名單,它仍然會返回客戶ids 1,2因爲它們匹配「英語」和「西班牙語」。 但是,結果應爲0行,因爲沒有客戶匹配所有三個術語。 我只想要客戶id返回,如果它匹配cust_lang表。 例如,給定一個列表:[「English」,「Spanish」] 我想讓結果成爲客戶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));` 

編輯2:我想我解決了它。我無意中在那裏有額外的選擇陳述。

回答

4

您可以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; 

如果,例如,你只是想檢查兩種語言,那麼你只需要改變你WHERE ... INHAVING條件,例如:

where l.language in ('English', 'Spanish') 

having count(*) = 2 
+0

如果我們改正'l.language'的'where' –

1

這是Gordon的答案,但它具有在語言列表上更靈活一點的好處,並且不需要對having子句進行任何更改。

with my_languages as (
    select langId from languages 
    where language in ('English', 'Spanish') 
) 
select cl.custId 
from cust_lang as cl inner join my_languages as l on l.langId = cl.langId 
group by cl.custId 
having count(*) = (select count(*) from lang) 
相關問題