如何在sql中创建子集查询?

时间:2012-08-04 19:52:14

标签: sql

我有两张表如下:

CREATE List (
    id   INTEGER,
    type INTEGER REFERENCES Types(id),
    data TEXT,
    PRIMARY_KEY(id, type)
);

CREATE Types (
    id   INTEGER PRIMARY KEY,
    name TEXT
);

现在我想创建一个查询,确定已赋予类型字符串的List的所有ID。

例如,

List:
1    0    "Some text"
1    1    "Moar text"
2    0    "Foo"
3    1    "Bar"
3    2    "BarBaz"
4    0    "Baz"
4    1    "FooBar"
4    2    "FooBarBaz"

Types:
0    "Key1"
1    "Key2"
2    "Key3"

如果输入“Key1”,“Key2”,则查询应返回1,4。

如果输入“Key2”,“Key3”,则查询应返回3,4。

给定输入“Key2”,查询应返回1,3,4。

谢谢!

3 个答案:

答案 0 :(得分:5)

select distinct l.id 
from list l
inner join types t on t.id = l.type
where t.name in ('key1', 'key2')
group by l.id
having count(distinct t.id) = 2

您必须将having子句调整为您在where子句中放置的键数。只有一个键的示例:

select distinct l.id 
from list l
inner join types t on t.id = l.type
where t.name in ('key2')
group by l.id
having count(distinct t.id) = 1

SQlFiddle example

答案 1 :(得分:2)

您可以使用以下技巧来扩展Jurgen的想法:

with keys as (
    select distinct t.id
    from types t
    where t.name in ('key1', 'key2')
)
select l.id 
from list l join
     keys k
     on l.type = keys.id cross join
     (select count(*) as keycnt from keys) k
group by l.id
having count(t.id) = max(k.keycnt)

即,计算子查询中的匹配键,然后将其用于计数。这样,您只需更改一行即可输入键值,并且您可以拥有任意数量的键。 (就像一个注释,我没有测试过这个SQL,所以我为任何语法错误道歉。)

答案 2 :(得分:1)

如果你可以动态生成SQL,这可能是许多DBMS中最有效的方法之一:

SELECT l.id
FROM   List  l
  JOIN Types t1  ON t1.id = l.type
  JOIN Types t2  ON t2.id = l.type
WHERE  t1.name = 'Key1'
  AND  t2.name = 'Key2' ;

看到这个类似的问题,有超过10种获得相同结果的方法,加上一些基准(对于Postgres): How to filter SQL results in a has-many-through relation