PostgreSQL 中的 WHERE 和 FILTER (WHERE) 有啥区别?
Posted
技术标签:
【中文标题】PostgreSQL 中的 WHERE 和 FILTER (WHERE) 有啥区别?【英文标题】:What's the difference between WHERE and FILTER (WHERE) in PostgreSQL?PostgreSQL 中的 WHERE 和 FILTER (WHERE) 有什么区别? 【发布时间】:2021-09-26 22:15:09 【问题描述】:总结和问题
我最近在 SO 上询问了 Postgres-related question 并得到了几个不同的答案,这些问题帮助我得到了我想要的结果。他们都工作,得到了正确的结果,并且都有非常相似的代码。但有一行不同:一个答案使用WHERE
子句来挑选我想要的东西,另一个使用FILTER (WHERE ...)
。这两者有什么区别?
背景细节
为了好奇,我问的是这张桌子:
+--+---------+-------+
|id|treatment|outcome|
+--+---------+-------+
|a |1 |0 |
|a |1 |1 |
|b |0 |1 |
|c |1 |0 |
|c |0 |1 |
|c |1 |1 |
+--+---------+-------+
我想要看起来像这样的东西:
+-----------------------+-----+
|ever treated |count|
+-----------------------+-----+
|0 |1 |
|1 |3 |
+-----------------------+-----+
我得到了两个有效的答案。这是第一个,来自@ErwinBrandstetter:
SELECT ever_treated, sum(outcome_ct) AS count
FROM (
SELECT id,
max(treatment) AS ever_treated,
count(*) FILTER (WHERE outcome = 1) AS outcome_ct
FROM t
GROUP BY 1
) sub
GROUP BY 1;
这是@Heidiki 和第二个:
select subq.ever_treated, sum(subq.count) as count
from (select id,
max(treatment) as ever_treated,
count(*) as count from t where outcome = 1
group by id) as subq
group by subq.ever_treated;
在我(诚然是新手)看来,两者之间的主要区别在于前者,您会看到:
count(*) FILTER (WHERE outcome = 1) AS outcome_ct
在后者中,你有这个:
count(*) as count from t where outcome = 1
我正在查看一些文档,我发现 FILTER
是在聚合级别工作,而 WHERE
可能不是,但我仍然迷失在直觉上,尤其是当它适用于我的表。
那么这里有什么不同呢?
【问题讨论】:
【参考方案1】:子查询不等价:
第一个
SELECT
id,
max(treatment) AS ever_treated,
count(*) FILTER (WHERE outcome = 1) AS outcome_ct
FROM t
GROUP BY 1
-
从
t
读取所有行。
计算整个表t
中每个id
的最大treatment
。
用outcome = 1
计算每个id
的行数。
第二个
select
id,
max(treatment) as ever_treated,
count(*) as count
from t
where outcome = 1
group by id
-
从
t
读取行的子集,其中outcome = 1
。
计算表格子集t
中每个id
的最大值treatment
。
计算子集中每个id
的行数(已过滤)。
就结果而言,只有#2 和#3 是显着的。如您所见,#3 是等价的,但 #2 不是。
【讨论】:
以上是关于PostgreSQL 中的 WHERE 和 FILTER (WHERE) 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
在 Postgresql 中的多个列上执行 WHERE IN
放置在 Sequelize 中的 WHERE 子句中的值,PostgreSQL 以获取所有内容
PostgreSQL 中的 SQL JOIN - WHERE 子句中的执行计划与 ON 子句中的不同
PostgreSQL 中的快速随机行:为啥 time (floor(random()*N)) + (select * from a where id = const) 比 select where i