oracle 保持时间范围的子表排序

pepwfjgg  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(93)

我正在使用一个表,该表维护每个键的记录历史,以及一个START_DATEEND_DATE字段,分别表示记录更改何时生效和失效:
| 关键|开始日期|结束日期|FIELD_ONE|领域二|
| --|--|--|--|--|
| 1 |2000-01-01| 2000-01-02| 10 | 20 |
| 1 |2000-01-03| 2000-01-04| 10 | 21 |
| 1 |2000-01-05| 2000-01-06| 11 | 21 |
| 1 |2000-01-07| 2000-01-08| 10 | 20 |
| 1 |2000-01-09| 2000-01-10| 10 | 21 |
FIELD_TWO与我的目的无关,所以我想在摘录中删除它。我最终得到了这样一张表:
| 关键|开始日期|结束日期|FIELD_ONE|
| --|--|--|--|
| 1 |2000-01-01| 2000-01-02| 10 |
| 1 |2000-01-03| 2000-01-04| 10 |
| 1 |2000-01-05| 2000-01-06| 11 |
| 1 |2000-01-07| 2000-01-08| 10 |
| 1 |2000-01-09| 2000-01-10| 10 |
但是现在,我的记录几乎彼此重复-START_DATEEND_DATE字段表示在我的子表中看不到的更改。所以我想把这个表“浓缩”成下面的结果:
| 关键|开始日期|结束日期|FIELD_ONE|
| --|--|--|--|
| 1 |2000-01-01| 2000-01-04| 10 |
| 1 |2000-01-05| 2000-01-06| 11 |
| 1 |2000-01-07| 2000-01-10| 10 |
如何做到这一点?
我天真地尝试在KEYFIELD_ONE上使用GROUP BY,并将MIN()MAX()函数应用于START_DATEEND_DATE字段,但这对上面的示例不起作用,其中FIELD_ONE在一个值(在本例中为10)之间来回变化。当然,你最终会得到以下结果:
| 关键|开始日期|结束日期|FIELD_ONE|
| --|--|--|--|
| 1 |2000-01-01| 2000-01-10| 10 |
| 1 |2000-01-05| 2000-01-06| 11 |
我正在使用PL/SQL,但只要PL/SQL具有相同的工具,就可以从其他SQL风格进行必要的翻译。
谢谢你,谢谢!

3j86kqsm

3j86kqsm1#

这是一个缺口和岛屿问题。您可以使用传统的解决方案:

select key,
  min(start_date) as start_date,
  max(end_date) as end_date, 
  field_one 
from (
  select
    x.*, 
    sum(case when prev_one = field_one and prev_end + 1 = start_date
        then 0 else 1 end) over(partition by key order by start_date) as g
  from (
    select t.*,
      lag(field_one) over(partition by key order by start_date) as prev_one,
      lag(end_date) over(partition by key order by start_date) as prev_end
    from t
  ) x
) y
group by key, g, field_one

测试结果:

KEY  START_DATE  END_DATE   FIELD_ONE 
 ---- ----------- ---------- --------- 
 1    01-JAN-00   04-JAN-00  10        
 1    05-JAN-00   06-JAN-00  11        
 1    07-JAN-00   10-JAN-00  10

请参见db<>fiddle上的运行示例。

相关问题