【问题标题】:Count the most recent number of consecutive rows with a null value计算具有空值的最近连续行数
【发布时间】:2020-05-28 10:09:25
【问题描述】:

我正在 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_unix DESC

想要的结果:

别名 1:包括 b/c,其 2 个最近的“requested_unix”值为空。

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

别名 3:包括 b/c,其 2 个最近的“requested_unix”值为空。旧的被丢弃。

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

别名 5:包括。连续 3 个最近的值为 null。

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

【问题讨论】:

  • 感谢您提供如此好的示例数据。我设置了一个 dbfiddle 供人们使用。 dbfiddle.uk/…
  • 这很酷。不知道小提琴已经来到了数据库。
  • 请始终公开您的 Postgres 版本。
  • 旁白:character varying(255)?见:stackoverflow.com/a/24560486/939860
  • 感谢您的更新!可能只是我遇到的任何文本字段的习惯。

标签: sql postgresql greatest-n-per-group window-functions gaps-and-islands


【解决方案1】:

使用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小提琴here

在子查询中,使用DISTINCT ON (alias) 检索每个alias 的一行。 ORDER BY 是我们需要的。

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

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

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

使用窗口函数(在DISTINCT ON之前处理)为每个分区添加行号(rn)、行数(ct)和最近的registered_unixmost_recent),你就拥有了所有信息在单个查询级别中是必需的。外层SELECT只是组装请求的结果格式。

相关:

【讨论】:

  • 你太棒了。谢谢。
猜你喜欢
  • 2018-11-04
  • 2014-04-21
  • 2015-09-15
  • 1970-01-01
  • 2020-03-07
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
  • 1970-01-01
相关资源
最近更新 更多