2013-07-18 37 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为了激起我对这个左外连接的兴趣... –