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 包含在 where 子句中

PostgreSQL 中的快速随机行:为啥 time (floor(random()*N)) + (select * from a where id = const) 比 select where i

使用函数更新PostgreSQL表中的数组