按每个项目至少有一个进行分组
Group by having at least one of each item
假设我有一个 table 匹配 person_id
s 到 pet
s。我有一份房主必须拥有的理想宠物清单(每种至少一只),从下面table,我想看看谁符合要求。
这个列表当然是 (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
s 至少拥有一只这些宠物——而不是全部。
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 只宠物的人。
这样做的一种方法是计算每个人有多少不同的宠物,并将其与不同宠物的总数进行比较(即加入):
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
编辑:
如果只考虑一些宠物 "ideal",并且预先知道此列表,则可以通过在 where
子句中引入此信息来大大简化查询:
SELECT person_id
FROM pets
WHERE pet IN ('dog', 'cat', 'tiger')
GROUP BY person_id
HAVING COUNT(DISTINCT pet) = 3
您可以通过单独计算每只宠物来做到这一点,如下所示:
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
(当该人拥有相应的宠物时),要么是 0
(当该人没有相应宠物时)。每个至少有一个的组将在 HAVING
子句的过滤器中产生 3
的总和。
假设我有一个 table 匹配 person_id
s 到 pet
s。我有一份房主必须拥有的理想宠物清单(每种至少一只),从下面table,我想看看谁符合要求。
这个列表当然是 (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
s 至少拥有一只这些宠物——而不是全部。
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 只宠物的人。
这样做的一种方法是计算每个人有多少不同的宠物,并将其与不同宠物的总数进行比较(即加入):
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
编辑:
如果只考虑一些宠物 "ideal",并且预先知道此列表,则可以通过在 where
子句中引入此信息来大大简化查询:
SELECT person_id
FROM pets
WHERE pet IN ('dog', 'cat', 'tiger')
GROUP BY person_id
HAVING COUNT(DISTINCT pet) = 3
您可以通过单独计算每只宠物来做到这一点,如下所示:
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
(当该人拥有相应的宠物时),要么是 0
(当该人没有相应宠物时)。每个至少有一个的组将在 HAVING
子句的过滤器中产生 3
的总和。