如何解决SELECT rows HAVING 结果等于来自 DISTINCT
我想返回与所有 key
都存在的 parts
匹配的结果。鉴于:
create table things (
id int not null,key int not null,part character varying(1),details character varying(64),CONSTRAINT things_pkey PRIMARY KEY (id)
);
还有这个:
id | 键 | 部分 | 详情 |
---|---|---|---|
1 | 1 | 一 | 1a 详情 |
2 | 1 | b | 1b 详情 |
3 | 1 | c | 1c 详情 |
4 | 2 | 一 | 2a 详情 |
5 | 2 | b | 2b 详情 |
6 | 2 | c | 2c 详情 |
7 | 3 | 一 | 3a 细节 |
8 | 3 | c | 3c 详情 |
9 | 4 | b | 4b 详情 |
10 | 5 | b | 5b 详情 |
11 | 6 | b | 6b 详情 |
12 | 6 | c | 6c 详情 |
13 | 7 | 一 | 7a 详情 |
14 | 8 | 一 | 8a 详情 |
我可以做到这一点:
id | 键 | 部分 | 详情 |
---|---|---|---|
1 | 1 | 一 | 1a 详情 |
2 | 1 | b | 1b 详情 |
3 | 1 | c | 1c 详情 |
4 | 2 | 一 | 2a 详情 |
5 | 2 | b | 2b 详情 |
6 | 2 | c | 2c 详情 |
使用此查询:
select *
from things t
where t.key in (
select x.key
from things x
group by x.key
having count(distinct part) = 3
);
但我真的想匹配不同的部分,而不仅仅是它的数量,例如having distinct part = ['a','b','c']
。我可以在查询中执行此操作还是仅在应用程序代码中执行此操作?
http://sqlfiddle.com/#!17/38b399/6
编辑
本质上,我所追求的是一大块行,其中存在 part
的所有 thing
。一件事有八个部分。它们将被处理并删除该表中的记录。永远重复。
这是来自 pgAdmin 的 CREATE
脚本(降低了噪音):
CREATE TABLE public.things (
id uuid PRIMARY KEY,key character varying(255) COLLATE pg_catalog."default" NOT NULL,part character varying(3) COLLATE pg_catalog."default" NOT NULL,details character varying(1024) COLLATE pg_catalog."default",timezone character varying(128) COLLATE pg_catalog."default",client_id uuid,CONSTRAINT things_client_id_fkey FOREIGN KEY (client_id)
REFERENCES public.clients (id)
);
CREATE INDEX things_client_id_index ON public.things (client_id);
CREATE UNIQUE INDEX unique_things ON public.things (key,part,client_id);
解决方法
基本上这可以被转换为 relational-division 的情况。
检查每个键的不同部分计数的查询必须处理表的所有行。此外,除此之外,不同 计数很昂贵。聚合和比较数组的成本甚至更高。
如果大多数行符合条件,那不会有太大区别,因为无论如何都会处理整个表。对于一个小的选择,任何这样的方法都表现得非常糟糕。相比之下,可以使用索引的替代查询技术将大放异彩。
理想情况下,您有一个单独的键表,每个相关键占一行。然后使用这样的东西:
SELECT *
FROM keys k
WHERE EXISTS (SELECT FROM things WHERE key = k.key AND part = 'a')
AND EXISTS (SELECT FROM things WHERE key = k.key AND part = 'b')
AND EXISTS (SELECT FROM things WHERE key = k.key AND part = 'c');
表 things
需要 (part,key)
上的多列索引以使其快速。
即使您没有 keys
表:
SELECT t1.key
FROM things t1
JOIN things t2 USING (key)
JOIN things t3 USING (key)
WHERE t1.part = 'a'
AND t2.part = 'b'
AND t3.part = 'c';
dbfiddle here
最佳查询取决于您对过滤器和结果格式的精确要求,以及精确架构定义。
相关:
,我认为 count(distinct)
可以满足您的需求。如果你想明确指定部分,你可以使用:
where t.key in (
select x.key
from things x
group by x.key
having array_agg(distinct part order by part)::text[] = array['a','b','c']
);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。