子集 a table 以包含仅与一组条目中的一次相关联的行
subset a table to include rows associated with only one occurence of a set of entries
我有以下 table 4 个人最喜欢的水果:
tbl
:
ID FRUIT
personA banana
personB apple
personC orange
personD grapefruit
personA avocado
personB banana
personC melon
personD pear
personA banana
我想提取仅与以下一项关联的 ID 的所有条目:香蕉、苹果、橙子。
这意味着我只希望提取 A 人和 C 人的行。B 人同时拥有(“苹果”和“香蕉”)。人 D 有 none 个想要的三个水果。
我目前有:
select *
from tbl t1
where exists (select 1
from tbl t2
where t1.ID=t2.ID and
(t2.fruit='banana' or
t2.fruit='apple' or
t2.fruit='orange'))
join (select ID, count(*) over (partition by t3.fruit)
from (select distinct ID, fruit
from tbl
where fruit='banana' or
fruit='apple' or
fruit='orange')) t3
on t3.ID=t.ID and
t3.cnt=1
是否有 better/simpler 方法来执行此操作?我想优化它以减少 运行 时间,因为 table 非常大。
desired table
:
ID FRUIT
personA banana
personC orange
personA avocado
personC melon
personA banana
我们可以使用 GROUP BY 和 HAVING COUNT(DISTINCT) 来找到我们想要的人。
SELECT
a.ID,
b.FRUITID
FROM tb1 a
JOIN tb1 b ON a.ID = b.ID
WHERE a.FRUITID IN ('banana', 'apple', 'orange')
GROUP BY
a.ID,
b.FRUITID
HAVING COUNT(DISTINCT a.FRUITID) = 1;
GO
ID | FRUITID
:------ | :------
personA | avocado
personA | banana
personC | melon
personC | orange
db<>fiddle here
子查询确定所有具有这三个水果的 ID,并计算它们有多少个水果。
你知道可以将 ID 加入到 table 并且只取那些只有 1 个水果的 ID,如果你也想要三个水果你并在加入条件中添加这个
SELECT
t1.ID, FRUIT
FROM
tbl t1
JOIN
(SELECT
ID, COUNT(DISTINCT FRUIT) countf
FROM
tbl
WHERE
FRUIT IN ('banana', 'apple', 'orange')
GROUP BY 1) t2 ON t1.ID = t2.ID AND t2.countf = 1;
另一种方法是使用 COUNT_IF:
SELECT *
FROM tbl t
QUALIFY COUNT_IF(t.fruit = 'banana') OVER(PARTITION BY ID) = 1
AND COUNT_IF(t.fruit = 'apple') OVER(PARTITION BY ID) = 1
AND COUNT_IF(t.fruit = 'orange') OVER(PARTITION BY ID) = 1;
答案:
这可以通过以下方式完成:
select *
from data
qualify count( distinct iff(fruit in ('apple','banana','orange'), fruit, null))
over(partition by id) = 1
给出:
ID
FRUIT
personA
avocado
personA
banana
personA
banana
personC
melon
personC
orange
工作原理:
可以通过显示 IFF and the COUNT DISTINCT 的中间状态来说明它是如何工作的,如下所示:
select *
,iff(fruit in ('apple','banana','orange'), fruit, null) as v
,count( distinct v) over(partition by id) as c
from data
给出:
ID
FRUIT
V
C
personA
avocado
1
personA
banana
banana
1
personA
banana
banana
1
personB
apple
apple
2
personB
banana
banana
2
personC
melon
1
personC
orange
orange
1
personD
grapefruit
0
personD
pear
0
因此personD
因没有魔法果实而被淘汰,personB
因拥有过多而被淘汰
如果您非常关心性能(我会测试),我认为 nbk 的解决方案执行速度最快。
我有以下 table 4 个人最喜欢的水果:
tbl
:
ID FRUIT
personA banana
personB apple
personC orange
personD grapefruit
personA avocado
personB banana
personC melon
personD pear
personA banana
我想提取仅与以下一项关联的 ID 的所有条目:香蕉、苹果、橙子。
这意味着我只希望提取 A 人和 C 人的行。B 人同时拥有(“苹果”和“香蕉”)。人 D 有 none 个想要的三个水果。
我目前有:
select *
from tbl t1
where exists (select 1
from tbl t2
where t1.ID=t2.ID and
(t2.fruit='banana' or
t2.fruit='apple' or
t2.fruit='orange'))
join (select ID, count(*) over (partition by t3.fruit)
from (select distinct ID, fruit
from tbl
where fruit='banana' or
fruit='apple' or
fruit='orange')) t3
on t3.ID=t.ID and
t3.cnt=1
是否有 better/simpler 方法来执行此操作?我想优化它以减少 运行 时间,因为 table 非常大。
desired table
:
ID FRUIT
personA banana
personC orange
personA avocado
personC melon
personA banana
我们可以使用 GROUP BY 和 HAVING COUNT(DISTINCT) 来找到我们想要的人。
SELECT a.ID, b.FRUITID FROM tb1 a JOIN tb1 b ON a.ID = b.ID WHERE a.FRUITID IN ('banana', 'apple', 'orange') GROUP BY a.ID, b.FRUITID HAVING COUNT(DISTINCT a.FRUITID) = 1; GO
ID | FRUITID :------ | :------ personA | avocado personA | banana personC | melon personC | orange
db<>fiddle here
子查询确定所有具有这三个水果的 ID,并计算它们有多少个水果。
你知道可以将 ID 加入到 table 并且只取那些只有 1 个水果的 ID,如果你也想要三个水果你并在加入条件中添加这个
SELECT
t1.ID, FRUIT
FROM
tbl t1
JOIN
(SELECT
ID, COUNT(DISTINCT FRUIT) countf
FROM
tbl
WHERE
FRUIT IN ('banana', 'apple', 'orange')
GROUP BY 1) t2 ON t1.ID = t2.ID AND t2.countf = 1;
另一种方法是使用 COUNT_IF:
SELECT *
FROM tbl t
QUALIFY COUNT_IF(t.fruit = 'banana') OVER(PARTITION BY ID) = 1
AND COUNT_IF(t.fruit = 'apple') OVER(PARTITION BY ID) = 1
AND COUNT_IF(t.fruit = 'orange') OVER(PARTITION BY ID) = 1;
答案:
这可以通过以下方式完成:
select *
from data
qualify count( distinct iff(fruit in ('apple','banana','orange'), fruit, null))
over(partition by id) = 1
给出:
ID | FRUIT |
---|---|
personA | avocado |
personA | banana |
personA | banana |
personC | melon |
personC | orange |
工作原理:
可以通过显示 IFF and the COUNT DISTINCT 的中间状态来说明它是如何工作的,如下所示:
select *
,iff(fruit in ('apple','banana','orange'), fruit, null) as v
,count( distinct v) over(partition by id) as c
from data
给出:
ID | FRUIT | V | C |
---|---|---|---|
personA | avocado | 1 | |
personA | banana | banana | 1 |
personA | banana | banana | 1 |
personB | apple | apple | 2 |
personB | banana | banana | 2 |
personC | melon | 1 | |
personC | orange | orange | 1 |
personD | grapefruit | 0 | |
personD | pear | 0 |
因此personD
因没有魔法果实而被淘汰,personB
因拥有过多而被淘汰
如果您非常关心性能(我会测试),我认为 nbk 的解决方案执行速度最快。