SQL连接表 - 检测某些元组的存在而不是其他元组

时间:2014-04-30 22:57:09

标签: sql join

我有两个主要表:codescategories。 我还有一个联接表code_mappings,它将代码与类别相关联。

我需要能够确定哪些代码映射到一组类别,但没有映射到另一组。一时间撞到我的脑袋,但我完全卡住了。

这是架构:

create table codes(
  id int,
  name varchar(256));

create table code_mappings(
  id int,
  code_id int,
  category_id int);

create table categories(
  id int,
  name varchar(256));

一些种子数据:

INSERT INTO categories VALUES(1, 'Dental');
INSERT INTO categories VALUES(2, 'Weight');
INSERT INTO categories VALUES(3, 'Other');
INSERT INTO categories VALUES(4, 'Acme Co');
INSERT INTO categories VALUES(5, 'No Name');

INSERT INTO codes VALUES(100, "big bag of cat food");
INSERT INTO codes VALUES(200, "healthy doggie treatz");

INSERT INTO code_mappings VALUES(50, 200, 1);
INSERT INTO code_mappings VALUES(51, 100, 4);
INSERT INTO code_mappings VALUES(52, 100, 3);

我如何编写一个查询,它将为我提供映射到类别(1,2,3)之一而不是其中一个类别(4,5)的代码?

2 个答案:

答案 0 :(得分:1)

这是set-within-sets查询的示例。我喜欢使用group byhaving来解决这些问题,因为我发现这是最灵活的方法:

select cm.code_id
from code_mappings cm
group by cm.code_id
having sum(case when cm.category_id in (1, 2, 3) then 1 else 0 end) = 1 and
       sum(case when cm.category_id in (4, 5) then 1 else 0 end) = 0;

having子句中的每个条件都实现了其中一个条件。你说一个代码是1,2或3,因此是= 1(如果你想要这三个中的至少一个,它将是> 0)。你说没有4或5,因此= 0

答案 1 :(得分:1)

SELECT *
FROM codes co
WHERE EXISTS (
    SELECT *
    FROM code_mappings ex
    WHERE ex.code_id = co.id
    AND ex.category_id IN (1,2,3)
    )
AND NOT EXISTS (
    SELECT *
    FROM code_mappings nx
    WHERE nx.code_id = co.id
    AND nx.category_id IN (4,5)
    )
    ;