“set-within-sets”的SQL查询排除

时间:2013-07-18 01:15:35

标签: mysql

我有一个包含两列的表item_categoryitem_idcat_id。项目与类别是多对多关系。

如果我的表看起来像这样......

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为2或7的情况下选择不具有任何行的category_id的不同列表(产生item_id s 2,3,5)?

6 个答案:

答案 0 :(得分: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

这是“set-within-sets”查询的示例。将group byhaving一起使用是此类查询的最通用形式。例如,如果您想确保包含类别3,则可以将having子句更改为:

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

答案 1 :(得分: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)
      )

答案 2 :(得分: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

两个查询的性能可能相似,但您可以测试数据集是否很大。

答案 3 :(得分: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

更新答案我认为这就是您的意思。

答案 4 :(得分: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.

分享并享受。

答案 5 :(得分:0)

可以使用简单的子查询来完成:

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