2013-07-18 66 views
2

我有一個表item_category有兩列:item_id,cat_id。項目到類別是一個多對多的關係。SQL查詢排除「set-set-sets」

如果我的表看起來像這樣...

item_id | cat_id 
1  | 1 
1  | 2 
2  | 3 
2  | 4 
3  | 5 
3  | 6 
4  | 7 
4  | 8 
5  | 9 
5  | 10 

...我怎樣才能選擇item_id個不同的列表沒有任何其中category_id爲2或7(產生item_id 2,3,5)?

回答

5

我會做到這一點使用的聚集和having條款:

select item_id 
from item_category ic 
group by item_id 
having max(cat_id = 2) = 0 and 
     max(cat_id = 7) = 0 

這是一個「設置中集」查詢的一個例子。使用group byhaving是這種查詢最普遍的形式。舉例來說,如果你想確保3類都包括在內,你會改變having子句:

having max(cat_id = 2) = 0 and 
     max(cat_id = 7) = 0 and 
     max(cat_id = 3) = 1 
+1

將我選擇的答案更改爲這個。雖然所有的答案都有效,但這是迄今爲止最快的。謝謝你的解釋,以及。 –

+0

'+ 1'我專注於表現。 –

+1

今天我學到了一些新的語法! – Curt

1

喜歡的東西:

SELECT DISTINCT item_category.item_id 
FROM item_category 
INNER JOIN (
       SELECT item_id ,SUM(CASE cat_id WHEN 2 THEN 1 WHEN 7 THEN 1 ELSE 0 END) AS catcount 
       FROM item_category 
       GROUP BY item_id 
      ) AS exclude 
     ON item_category .item_id = exclude.item_id 
      WHERE exclude.catcount=0 

更新的答案,我想這是你的意思。

+0

有了這個查詢,我還是會回來'item_id'的1和4 –

+0

耶更新查詢再次閱讀您的問題。新的一個對我的測試數據有效 – Namphibian

2

我會使用一個嵌套的SELECT,雖然有可能用self join做到這一點。

select item_id 
from item_category t 
where not exists (
    select 1 
    from item_category 
    where item_id = t.item_id 
     and cat_id in (2,7) 
) 
group by item_id; 

Example

你也可以使用一個NOT IN條款改爲:

SELECT DISTINCT item_id 
FROM item_category 
WHERE item_id NOT IN (
    select distinct item_id 
    from item_category 
    where cat_id in (2,7)); 

Example

兩個查詢可能是在性能上相似,但你可以測試,如果你的數據集大。

+0

第一個很好,謝謝!現在就要基準測試... –

3

嘗試這樣:

SELECT DISTINCT item_id 
FROM table_category 
WHERE item_id NOT IN 
     ( select distinct item_id 
      from item_category 
      where cat_id in (2,7) 
    ) 
+0

爲什麼downvote?請解釋... –

+1

錯誤點擊。我編輯了這篇文章,以便我可以修復downvote,並使其成爲upvote。 – Curt

0

它可以用一個簡單的子查詢來完成:

SELECT DISTINCT item_id 
FROM ic 
WHERE item_id NOT IN (
    SELECT DISTINCT item_id FROM ic WHERE cat_id IN (2,7) 
); 
+0

這個確切的答案已經發布。 –

+0

我知道! Fabien在我工作的時候提交了他的報告。 –

+1

但我的看起來更好;) –

1

一種方法是

SELECT DISTINCT ITEM_ID 
    FROM ITEM_CATEGORY 
    WHERE ITEM_ID NOT IN (SELECT DISTINCT ITEM_ID 
          FROM ITEM_CATEGORY 
          WHERE CATEGORY_ID IN (2, 7)) 

產生你想要的結果。如果你想有更多的樂趣,你可以做

SELECT DISTINCT ic1.ITEM_ID 
    FROM ITEM_CATEGORY ic1 
    LEFT OUTER JOIN (SELECT DISTINCT ITEM_ID 
        FROM ITEM_CATEGORY 
        WHERE CATEGORY_ID IN (2, 7)) ic2 
    ON ic2.ITEM_ID = ic1.ITEM_ID 
    WHERE ic2.ITEM_ID IS NULL 

這也可以讓你要尋找的結果,如果你不熟悉LEFT OUTER JOIN如何工作,可能使一個有趣的時間通過它的工作方式和原因而令人費解。

SqlFiddle here.

分享和享受。

+0

+1爲了激起我對這個左外連接的興趣... –