我有一个数据集如下,我想从中得出一些推论.

Id Nbr Dt Status Cont1Sta1 DateLagInDays Recurrence
1 2 2023-10-1 1
1 2 2023-11-2 0
1 2 2023-12-13 0
1 3 2023-10-1 0
1 3 2023-11-2 0
1 3 2023-12-13 1
1 9 2023-11-1 0
1 9 2023-12-1 1
1 9 2024-1-1 0

我已经创建了一个基于ID, number的SQL Server数据分区,并按照dt的升序排序.

所需的推论如下:

  1. 对于所选分区,是否存在任何状态= 1的实例.
  2. 如果#1为true,则是状态= 0的最早实例与该行的状态= 1之间的日期差.
  1. 在分区内,在至少有一行状态= 1后,是否有任何新行忽略状态值?

使用分区基本逻辑可以实现这一点吗?我确实try 在分区中使用滞后和前导,但它不会产生一个好的结果.

任何关于编写一个好的简洁代码的建议都是有帮助的.

虽然我try 了一些其他的东西,我有以下干净的代码,我目前正在使用.我希望在转换后的第一个实例行中,每个分区都填充Cont1Sta1、DateLagInDays、Recurrence列.

declare @t table
(
    id int,
    nbr int,
    dt date,
    status smallint,
    Cont1Sta1 bit,--if the chosen partition has atleast one status=1
    DateLagInDays int,--date diff in days from earliest record within partition to when status=1
    Recurrence bit --does partition has atleast one new row after one possible row that has status=1
)
insert into @t(id,nbr,dt,status) select 1,9,'2023-11-1',0
insert into @t(id,nbr,dt,status) select 1,9,'2023-12-1',1
insert into @t(id,nbr,dt,status) select 1,9,'2024-1-1',0
insert into @t(id,nbr,dt,status) select 1,2,'2023-10-1',1
insert into @t(id,nbr,dt,status) select 1,2,'2023-11-2',0
insert into @t(id,nbr,dt,status) select 1,2,'2023-12-13',0
insert into @t(id,nbr,dt,status) select 1,3,'2023-10-1',0
insert into @t(id,nbr,dt,status) select 1,3,'2023-11-2',0
insert into @t(id,nbr,dt,status) select 1,3,'2023-12-13',1;

select 
    id, nbr, dt,status,
    rank() over (partition by id, nbr, status order by id, nbr, dt asc, status desc) rownbr
from 
    @t
order by 
    id, nbr, dt asc, status desc;

以下是所需的表格结果:

Id Nbr Dt Status Cont1Sta1 DateLagInDays Recurrence
1 2 2023-10-1 0 1 32 1
1 2 2023-11-2 1 0 0 0
1 2 2023-12-13 0 0 0 0
1 3 2023-10-1 0 1 73 0
1 3 2023-11-2 0 0 0 0
1 3 2023-12-13 1 0 0 0
1 9 2023-11-1 1 1 0 1
1 9 2023-12-1 0 0 0 0
1 9 2024-1-1 0 0 0 0

推荐答案

解释逻辑的注释嵌入在查询中.

with cte as (
    select id, nbr, dt, status
        -- get a row number so we can only show the calculated data once per partition
        , row_number() over (partition by id, nbr order by id, nbr, dt asc, status desc) rn
        -- Determine whether status 1 exists within the partition
        , max(status) over (partition by id, nbr) partition_status
        -- Get the first date where Status = 1
        , min(case when Status = 1 then dt else null end) over (partition by id, nbr) partition_dt1
        -- Get the last date where Status = 1
        -- Only required if there is the possibility of more than one Status = 1 row in a partition
        , max(case when Status = 1 then dt else null end) over (partition by id, nbr) partition_dt2
    from @t
)
select id, nbr, dt, status
    -- On the first row of each partition show whether a status = 1 exists
    , case when rn = 1 then partition_status else 0 end Cont1Sta1
    -- On the first row of each partition show the date lag in days
    , case when rn = 1 then datediff(day, dt, coalesce(partition_dt1, dt)) else 0 end DateLagInDays
    -- On the first row of each partition show whether any records exist after the last Status = 1
    , case when rn = 1 and exists (select 1 from cte c2 where c2.id = c1.id and c2.nbr = c1.nbr and c2.dt > c1.partition_dt2) then 1 else 0 end Recurrence
from cte c1
order by id, nbr, dt asc, status desc;

按要求返回:

id nbr dt status Cont1Sta1 DateLagInDays Recurrence
1 2 2023-10-01 1 1 0 1
1 2 2023-11-02 0 0 0 0
1 2 2023-12-13 0 0 0 0
1 3 2023-10-01 0 1 73 0
1 3 2023-11-02 0 0 0 0
1 3 2023-12-13 1 0 0 0
1 9 2023-11-01 0 1 30 1
1 9 2023-12-01 1 0 0 0
1 9 2024-01-01 0 0 0 0

DBFiddle

Sql相关问答推荐

SQL查询组类值在同一行中,并连接和排序其他值

在甲骨文中查找前一个星期一的S日期

从原始表列中经过JSON字符串化的对象数组构建视图

使用DatePart函数对日期时间值进行分组

将FLOAT转换为VARBINARY,然后再转换回FLOAT

如何将不同层次的产品组和规格组合到最深一层?

Postgres SQL查询从字符串中获取邮箱地址

Postgres jsonpath运算符的变量替换,如_regex?

查找滑动窗口框架中的最大和最小列值

SQL根据另一列的顺序和值获取组中的最后一列

两个具有 NULL 值的表达式结果之间的差异

SQL Server - 判断 ids 层次 struct 中的整数 (id)

正则表达式:停在第一个匹配的其中一个字符位置上

SQL获取两个日期范围之间的计数

SQL 函数 DIFFERENCE 返回有趣的分数

如何按日期和位置对最近 3 个报告日期的 SQL 查询结果进行透视?

添加一列并根据其他列值进行填充

查找具有相同连接列数据的所有记录

如何根据 Amazon Athena 中的多个列值删除重复行?

每组跨行曲折?