Sql 使用空值计算最近的连续行数

Sql 使用空值计算最近的连续行数,sql,postgresql,greatest-n-per-group,window-functions,gaps-and-islands,Sql,Postgresql,Greatest N Per Group,Window Functions,Gaps And Islands,我正在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,

我正在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');
我试图计算
请求的\u unix
为空的连续
别名
行数,但仅限于第一次出现,且连续出现的行数大于或等于2

数据按别名排序,然后注册unix DESC:

预期结果:

别名1:包含b/c,其最近的2个“请求的unix”值为空

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

别名3:包含b/c,其最近的两个“请求的unix”值为空。旧的被丢弃了

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

别名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);
小提琴

在子查询中,使用
DISTINCT ON(别名)
为每个
别名检索一行<代码>订购方式
使其成为我们需要的

  • 第一个按项目排序的别名必须与上的不同项一致

  • 第二个按项目排序的请求为空将notnull值排序在顶部。(
    FALSE
    TRUE
    之前排序)
    请求的\u unix不是NULL DESC
    可能更直观,但我更喜欢短代码

  • 第三个按项目排序的项目
    registered\u unix DESC
    从这些项目中选择最新的一行

使用窗口函数(在上进行DISTINCT处理之前)为每个分区添加行号(
rn
)、行计数(
ct
)和最近注册的
unix
最近注册的
)即可在单个查询级别中获得所有必要信息。外部
SELECT
仅用于组装请求的结果格式

相关的:


感谢您提供了这么好的示例数据。我为大家准备了一把小提琴。那太酷了。不知道数据库中出现了Fiddle。请始终披露您的Postgres版本。旁白:
字符变化(255)
?请参阅:谢谢您的更新!可能只是我遇到的任何文本字段的习惯。你太棒了。非常感谢。