我需要通过将开始日期和结束日期与之前的日期进行比较来清理表上的期间组,以查看是否存在相等.

一个例子胜过千言万语:

my key start date end date tech date
A 2022-05-01 9999-12-31 2022-05-01
A 2023-01-01 9999-12-31 2023-01-01
A 2023-01-01 2023-05-01 2023-05-01
A 2023-07-01 9999-12-31 2023-07-01

因此,我需要确定两个时期:

my key start date end date
A 2022-05-01 2023-05-01
A 2023-07-01 9999-12-31

我想到的一个 Select 是,当开始日期或结束日期与前一行相同(按技术日期排序)时对我的数据进行"分组":

my key start date end date tech date group comment
A 2022-05-01 9999-12-31 2022-05-01 1 first group of key A
A 2023-01-01 9999-12-31 2023-01-01 1 same group as previous because end dates are equals
A 2023-01-01 2023-05-01 2023-05-01 1 same group as previous because start dates are equals
A 2023-07-01 9999-12-31 2023-07-01 2 new group because start and end dates are different from the previous row

然后计算开始日期为该组的最小值,结束日期为该组的最大值(需要时不包括9999-12-31)

但我很难正确地对行进行分组,我try 了分析函数,但我找不到一种方法来获得前一个计算组:

select mykey, startdate, enddate, techdate,
  case when lag(startdate,1,startdate) over (partition by mykey order by techdate) = startdate
       or lag(enddate,1,enddate) over (partition by mykey order by techdate) = enddate
    then lag(grp,1,grp) over (partition by mykey order by techdate)
    else grp
end as calc_grp
from (select mykey, startdate, enddate, techdate, row_number() over (partition by mykey order by techdate) as grp from mytable)

我try 了一些这样的查询,但当然不起作用 我应该使用LAG(calc_grp...),但这是不可能的

你有什么办法实现这一点吗?

如果这是不可能的,我应该能够用另一种方法计算正确的值.

推荐答案

有很多方法可以简化它.如果你看一下中间的cte结果,我相信你会得到一些 idea .

关键是要确定各时期的界限.因此,定义一个二进制周期变化条件指示符将得到一个可以求和以获得周期id的值.

然后,只需根据tech_date Select 该时段中最早的开始日期,并按tech_date for each 时段 Select 最晚的结束日期.剥cat 皮的方法有很多.

CREATE VOLATILE TABLE my_temp_table (
    my_key VARCHAR(255),
    start_date DATE FORMAT 'YYYY-MM-DD',
    end_date DATE FORMAT 'YYYY-MM-DD',
    tech_date DATE FORMAT 'YYYY-MM-DD'
) ON COMMIT PRESERVE ROWS;

INSERT INTO my_temp_table (my_key, start_date, end_date, tech_date) VALUES ('A', DATE '2022-05-01', DATE '9999-12-31', DATE '2022-05-01');
INSERT INTO my_temp_table (my_key, start_date, end_date, tech_date) VALUES ('A', DATE '2023-01-01', DATE '9999-12-31', DATE '2023-01-01');
INSERT INTO my_temp_table (my_key, start_date, end_date, tech_date) VALUES ('A', DATE '2023-01-01', DATE '2023-05-01', DATE '2023-05-01');
INSERT INTO my_temp_table (my_key, start_date, end_date, tech_date) VALUES ('A', DATE '2023-07-01', DATE '9999-12-31', DATE '2023-07-01');


with 
find_period_changes as (
select mtt.*,
       row_number() over ( partition by my_key order by tech_date ) as rn,
       case when coalesce(lag(start_date) over ( partition by my_key order by tech_date),date '1900-01-01') <> start_date
             and coalesce(lag(end_date) over ( partition by my_key order by tech_date),date '1900-01-01') <> end_date then 1 else 0 
        end as start_new_period
  from my_temp_table mtt),
group_periods as (
select a.*,
       sum(start_new_period) over ( partition by my_key
                                        order by tech_date
                                    rows between unbounded preceding and current row) as period_id
  from find_period_changes a),
start_and_end_rns as (
select my_key,
       period_id,
       min(rn) over ( partition by my_key,
                                   period_id) as period_start_rn,
       max(rn) over ( partition by my_key,
                                   period_id) as period_end_rn
  from group_periods)
select distinct
       sae.my_key,
       mtt_start_date.start_date,
       mtt_end_date.end_date
  from start_and_end_rns sae
 inner
  join find_period_changes mtt_start_date
    on sae.my_key = mtt_start_date.my_key
   and sae.period_start_rn = mtt_start_date.rn
 inner
  join find_period_changes mtt_end_date
    on sae.my_key = mtt_end_date.my_key
   and sae.period_end_rn = mtt_end_date.rn;

Sql相关问答推荐

在postgresql中使用来自另一个字段的日期名称作为JSONB查询中的关键字

如何解决Error:operator is not unique:unknown—unknown在一个动态SQL查询?""""

基于多列比较连接两个表

PostgreSQL抽奖查询

为什么我的SQL标量函数有时会抛出";子查询返回多个值.这是不允许的.

在SQL Server中设置关联对象的有效JSON格式

如何在连接中使用三个不同的列,从而在PostgreSQL中只获得两个列?

TSQL如何为群分配号码

将SQL Server查询改进为;线程安全;

将二维数组的第一个和第二个元素取消嵌套到两个一维数组中

根据具有特定值的 ID 创建自定义组

我们可以使用连接改进包含多个子查询的查询吗

验证某个日期前后的连续代码

REGEXP_SUBSTR使用方法

如何创建一个递归计数器来查找一个元素有多少父级和子级?

joins 组合多个重复数据删除策略

如何在 SQL Server 中将 -13422.8450 舍入到 -13422.84

以 15 分钟为间隔的使用情况SQL 查询

多列上的 SQL UNIQUE 约束 - 它们的组合必须是唯一的还是至少其中之一?

在 PostgreSQL 中,如何将数组中的每个元素用作另一个表中的键?