通过至少有一个项

时间:2015-08-20 15:49:26

标签: sql postgresql select relational-division

假设我有一个与person_id匹配pet的表格。我有一份房主必须拥有的理想宠物清单(至少有一种),从下表中我想看看谁符合要求。

该列表当然是(dog, cat, tiger)。人们绝对可以拥有多个,但这些是必不可少的(因此person_id = 1是唯一有效的人。)

+---------+-----------+--------+
| home_id | person_id |  pet   |
+---------+-----------+--------+
|       1 |         1 | dog    |
|       2 |         1 | dog    |
|       3 |         1 | cat    |
|       4 |         1 | tiger  |
|       5 |         2 | dog    |
|       6 |         2 | cat    |
|       7 |         3 | <null> |
|       8 |         4 | tiger  |
|       9 |         4 | tiger  |
|      10 |         4 | tiger  |
+---------+-----------+--------+

我已经能够通过跑步来检查谁有老虎或猫:

select person_id, pet 
from house 
group by person_id having pet in ('dog','cat','tiger'), 

但显然这给了person_id至少有一只宠物 - 而不是所有宠物。

3 个答案:

答案 0 :(得分:3)

这样做的一种方法是计算每个人有多少不同的宠物,并将它(即加入它)与不同宠物的总数进行比较:

SELECT person_id
FROM   (SELECT   person_id, COUNT(DISTINCT pet) AS dp
        FROM     pets
        GROUP BY person_id) a
JOIN   (SELECT COUNT(DISTINCT pet) AS dp FROM pets) b ON a.dp = b.dp

编辑:
如果只考虑一些宠物&#34;理想&#34;,并且此列表是预先知道的,则可以通过在where子句中引入此信息来大大简化查询:

SELECT   person_id
FROM     pets
WHERE    pet IN ('dog', 'cat', 'tiger')
GROUP BY person_id
HAVING   COUNT(DISTINCT pet) = 3

答案 1 :(得分:2)

你可以通过单独计算每只宠物来做到这一点:

select
    person_id 
FROM MyTable
GROUP BY person_id
HAVING 3 = (
    MAX(CASE pet WHEN 'dog' THEN 1 ELSE 0 END)
+   MAX(CASE pet WHEN 'cat' THEN 1 ELSE 0 END)
+   MAX(CASE pet WHEN 'tiger ' THEN 1 ELSE 0 END)
)

当该人拥有相应的宠物时,组中的每个MAX都可以1,或者当该人没有这种宠物时,03。具有至少一个的组将在HAVING子句的过滤器中生成ViewHolder的总和。

答案 2 :(得分:1)

select person_id
from house 
where pet = 'dog'
intersect
select person_id
from house 
where pet = 'cat'
intersect
select person_id
from house 
where pet = 'tiger'

您可以使用intersect来吸引拥有所有3只宠物的人。