在什么情况下,间隙和岛屿需要计数(x 或空)?

Eva*_*oll 2 postgresql null count window-functions gaps-and-islands

这个答案中,Erwin Brandstetter 说:

count(step OR NULL) OVER (ORDER BY date)是最短的语法,也适用于 Postgres 9.3 或更早版本。count()只计算非空值。在现代 Postgres 中,更简洁、等效的语法是:

count(step) FILTER (WHERE step) OVER (ORDER BY date)
Run Code Online (Sandbox Code Playgroud)

我不确定为什么count(step OR NULL)是首选。在我的查询中,我执行以下操作。我重命名了我的变量以匹配他的同时保持语法。

CASE WHEN lag(id_type) OVER (ORDER BY date) <> id_type THEN 1 END AS step
Run Code Online (Sandbox Code Playgroud)

我们正在计算它返回的值。请注意,case 只能返回 1 或 null。

  • 如果两者不相等,则返回 1。
  • 如果它们相等,则返回不计算在内的 null。

欧文的回答是:

这假设涉及的列是NOT NULL. 否则你需要做更多。

所以我更迷茫了。添加count(step OR NULL)什么来保护我们的查询有什么意义?

任何人都可以分解这一点,也许可以展示两个带有数据的示例,其中只有一个 - 一个 -count(x OR NULL)有效?

Erw*_*ter 5

这都是关于 NULL 处理的。该表达式的lag(id_type) OVER (ORDER BY date) <> id_type计算结果为布尔值,可以是TRUE,FALSENULL。如果左操作数或右操作数为 NULL,我们得到 NULL。可以通过多种方式在任一侧引入 NULL:

  • 没有前一行(或下一行或相关情况下的类似行)。
  • 基础表中的列可以为 NULL。
  • AnOUTER JOIN引入 NULL(未找到匹配的行)。
  • 涉及可以评估为 NULL 的表达式。

有多种方法可以将三值逻辑折叠为两种情况。一个CASE语句,一个OR表达式等。相关答案的详细信息:

这是所涉及技术的比较,以及(更新的)基准测试。基本上,它们都执行相同的操作,这是一种廉价的操作。FILTER引入 Postgres 9.4的聚合子句在更新的基准测试中似乎更快了一点:

没有案例wherein only one of them works,技术是可以互换的。计数或求和的内容完全取决于设置和要求的详细信息。在这种情况下,我们只计算TRUE- 只要基础表或查询产生所有非空值(第一行的极端情况有待讨论)。

而这个案例只需要简单的比较。相关案例需要更仔细地查看上一个或下一个值。然后,将默认值作为第三个参数提供给lag()or可能会派上用场lead()


Eva*_*oll 5

据我所知,这都是关于处理false not null。有了代码和一些普通的背景count():情况count(x OR NULL)是这样的:x=false

  1. 香草count()捕捉到错误。这将返回 1。

    SELECT count(x)
    FROM ( VALUES (false) ) AS t(x);
    
    Run Code Online (Sandbox Code Playgroud)
  2. CASEFolding,将 false 折叠为 null,与 false 不同的是,它count()排除了 null。这将返回 0。

    SELECT count(x)
    FROM ( VALUES (CASE WHEN false THEN 1 END) ) AS t(x);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 短路法评估false OR null,从而null排除count()。这将返回 0。

    SELECT count(x OR NULL)
    FROM ( VALUES (false) ) AS t(x);
    
    Run Code Online (Sandbox Code Playgroud)
  4. FILTER方法,将 x 计算为 bool。跳过 false 值和 null 值,将其他所有内容 (true) 发送到count(). 这将返回 0。

    SELECT count(x) FILTER (WHERE x)
    FROM ( VALUES (false) ) AS t(x);
    
    Run Code Online (Sandbox Code Playgroud)

结论

在我的例子中,我使用方法2,Erwin使用方法3既不是修复也不是更好;既不是更优化也不是更快。