计算具有空值的最近连续行数

Count the most recent number of consecutive rows with a null value

我正在基于此演示设置在 PostgreSQL 10.6 中进行一些数据分析:

create table history (
    registered_unix int,
    requested_unix int,
    alias character varying(255)
);

INSERT INTO history VALUES
  (1537841388, 1537878224, '3')
, (1538093202, 1538095740, '1')
, (1538093186, 1538095740, '3')
, (1538105501, 1538107039, '2')
, (1538105501, 1538107039, '4')
, (1538205007, 1538242243, '2')
, (1538205012, NULL      , '1')
, (1538105501, NULL      , '1')
, (1538205007, NULL      , '3')
, (1538105501, NULL      , '3')
, (1538040863, NULL      , '3')
, (1537985996, NULL      , '3')
, (1538205007, NULL      , '4')
, (1538093186, NULL      , '4')
, (1538205301, NULL      , '5')
, (1538105501, NULL      , '5')
, (1538093186, NULL      , '5');

我正在尝试计算 requested_unix 为空的连续 alias 行的数量,但仅针对第一次出现且连续出现大于或等于 2 的行数。

数据按别名排序,然后registered_unixDESC:

想要的结果:

别名 1:包括 b/c 它的 2 个最近的 "requested_unix" 值为空。

别名 2:已跳过。请求的 unix 在其最近的行上有一个值

别名 3:包括 b/c 它最近的 2 个 "requested_unix" 值为空。旧的被丢弃。

别名 4:已跳过。只有 1 个最新的 "requested_unix" 值为空。第二行有一个值。

别名 5:包含。连续 3 个最近的值为空。

有各种统计连续出现次数或找到第一次出现次数的票,但我似乎想把这两种方法结合起来。

使用DISTINCT ON,我们只需要一个子查询:

SELECT alias
     , CASE WHEN requested_unix IS NULL THEN ct   ELSE rn - 1          END AS missed
     , CASE WHEN requested_unix IS NULL THEN NULL ELSE registered_unix END AS last_success
     , most_recent
FROM  (
   SELECT DISTINCT ON (alias)
          *
        , row_number()         OVER (PARTITION BY alias ORDER BY registered_unix DESC) AS rn
        , count(*)             OVER (PARTITION BY alias) AS ct
        , max(registered_unix) OVER (PARTITION BY alias) AS most_recent
   FROM   history h
   ORDER  BY alias, requested_unix IS NULL, registered_unix DESC
   ) latest_success
WHERE (requested_unix IS NULL OR rn > 2);

db<>fiddle here

在子查询中,每个 aliasDISTINCT ON (alias) 检索一行。 ORDER BY 使它成为我们需要的。

  • 第一个 ORDER-BY 项目 alias 必须与 DISTINCT ON 一致。

  • 第二个 ORDER-BY 项 requested_unix IS NULL 将非空值排序在顶部。 (FALSETRUE 之前排序。)requested_unix IS NOT NULL DESC 可能更直观,但我更喜欢短代码。

  • 第 3 个 ORDER-BY 项 registered_unix DESC 选择其中的 最新 行。

添加行号 (rn)、行数 (ct) 和每个分区的最新 registered_unix (most_recent) window函数(在 DISTINCT ON 之前处理),并且您在单个查询级别中拥有所有必要的信息。外层的SELECT只是为了assemble请求的结果格式。

相关:

  • Select first row in each GROUP BY group?
  • Sorting null values after all others, except special
  • Best way to get result count before LIMIT was applied