将连续的日期有效期合并在一起

达尼洛(Danilo Piazzalunga)

我有一系列记录,其中包含一些具有时间有效性的信息(产品类型)。

如果分组信息(产品类型)保持不变,我想将相邻的有效期合并在一起。我不能GROUP BYMIN一起使用简单的方法MAX,因为某些产品类型(A在示例中为)可以“消失”和“返回”。

使用Oracle 11g。

MySQL的类似问题是:如何在MySQL中进行连续分组依据?

输入数据

| PRODUCT |                       START_DATE |                         END_DATE |
|---------|----------------------------------|----------------------------------|
|       A |      July, 01 2013 00:00:00+0000 |      July, 31 2013 00:00:00+0000 |
|       A |    August, 01 2013 00:00:00+0000 |    August, 31 2013 00:00:00+0000 |
|       A | September, 01 2013 00:00:00+0000 | September, 30 2013 00:00:00+0000 |
|       B |   October, 01 2013 00:00:00+0000 |   October, 31 2013 00:00:00+0000 |
|       B |  November, 01 2013 00:00:00+0000 |  November, 30 2013 00:00:00+0000 |
|       A |  December, 01 2013 00:00:00+0000 |  December, 31 2013 00:00:00+0000 |
|       A |   January, 01 2014 00:00:00+0000 |   January, 31 2014 00:00:00+0000 |
|       A |  February, 01 2014 00:00:00+0000 |  February, 28 2014 00:00:00+0000 |
|       A |     March, 01 2014 00:00:00+0000 |     March, 31 2014 00:00:00+0000 |

预期结果

| PRODUCT |                      START_DATE |                         END_DATE |
|---------|---------------------------------|----------------------------------|
|       A |     July, 01 2013 00:00:00+0000 | September, 30 2013 00:00:00+0000 |
|       B |  October, 01 2013 00:00:00+0000 |  November, 30 2013 00:00:00+0000 |
|       A | December, 01 2013 00:00:00+0000 |     March, 31 2014 00:00:00+0000 |

请参阅完整的SQL Fiddle

亚历克斯·普尔

这是一个孤岛问题。有多种解决方法。这使用leadlag分析功能:

select distinct product,
  case when start_date is null then lag(start_date)
    over (partition by product order by rn) else start_date end as start_date,
  case when end_date is null then lead(end_date)
    over (partition by product order by rn) else end_date end as end_date
from (
  select product, start_date, end_date, rn
  from (
    select t.product,
      case when lag(end_date)
          over (partition by product order by start_date) is null
        or lag(end_date)
          over (partition by product order by start_date) != start_date - 1
        then start_date end as start_date,
      case when lead(start_date)
          over (partition by product order by start_date) is null
        or lead(start_date)
          over (partition by product order by start_date) != end_date + 1
        then end_date end as end_date,
      row_number() over (partition by product order by start_date) as rn
    from t
  )
  where start_date is not null or end_date is not null
)
order by start_date, product;

PRODUCT START_DATE END_DATE
------- ---------- ---------
A       01-JUL-13  30-SEP-13 
B       01-OCT-13  30-NOV-13 
A       01-DEC-13  31-MAR-14 

SQL小提琴

最里面的查询查看产品的前后记录,并且仅在记录不连续时才保留开始和/或结束时间:

select t.product,
  case when lag(end_date)
      over (partition by product order by start_date) is null
    or lag(end_date)
      over (partition by product order by start_date) != start_date - 1
    then start_date end as start_date,
  case when lead(start_date)
      over (partition by product order by start_date) is null
    or lead(start_date)
      over (partition by product order by start_date) != end_date + 1
    then end_date end as end_date
from t;

PRODUCT START_DATE END_DATE
------- ---------- ---------
A       01-JUL-13            
A                            
A                  30-SEP-13 
A       01-DEC-13            
A                            
A                            
A                  31-MAR-14 
B       01-OCT-13            
B                  30-NOV-13 

select的下一个级别将删除那些处于中期的日期,其中两个日期都被内部查询覆盖,从而得到:

PRODUCT START_DATE END_DATE
------- ---------- ---------
A       01-JUL-13            
A                  30-SEP-13 
A       01-DEC-13            
A                  31-MAR-14 
B       01-OCT-13            
B                  30-NOV-13 

然后外部查询折叠这些相邻对;我使用了创建重复项,然后使用消除重复项的简单distinct方法,但是您可以通过其他方式进行操作,例如将两个值都放入一对行中,然后将两个值都保留为另一个空值,然后用另一个值消除它们选择层,但我认为在这里完全可以。

如果您的实际用例有时间,而不仅仅是日期,那么您需要在内部查询中调整比较;而不是+/- 1,可能是1秒的间隔,或者如果您愿意,则是1/86400,但取决于值的精度。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将连续的日期有效期合并在一起

来自分类Dev

将开始日期和结束日期表中的事件合并在一起

来自分类Dev

是否有将cobertura coverage xml报告合并在一起的方法?

来自分类Dev

将列中具有相同值的行合并在一起

来自分类Dev

如何将没有选择字段的两个选择合并在一起?

来自分类Dev

将两个表合并在一起,其中所有列都不匹配

来自分类Dev

如何将Git日志合并在一起?

来自分类Dev

如何将两个嵌套词典合并在一起?

来自分类Dev

将视频与AVMutableComposition合并在一起不会导致音频

来自分类Dev

将PDF合并在一起后如何解锁文件以进行删除

来自分类Dev

将数组中的相同值合并在一起

来自分类Dev

在if语句下将两个for循环合并在一起

来自分类Dev

R:将2列中的信息合并在一起

来自分类Dev

SQL将多行合并在一起的表

来自分类Dev

将两个ggplot()boxplots合并在一起

来自分类Dev

如何将两个盖茨比站点合并在一起

来自分类Dev

使用Merge.xts函数将多个xts文件合并在一起

来自分类Dev

将List <T>的多个集合与对象的混合类型合并在一起?

来自分类Dev

使用php将两个csv文件合并在一起

来自分类Dev

如何将两个列表合并在一起?

来自分类Dev

如何将Git日志合并在一起?

来自分类Dev

VBA代码将两个单元合并在一起

来自分类Dev

将证书合并在一起?Ubuntu 16.04?

来自分类Dev

使用 dplyr 将多列合并在一起

来自分类Dev

使用 node.js 将 dataobj 合并在一起

来自分类Dev

根据命令行参数将字符串合并在一起。

来自分类Dev

将两个数组合并在一起

来自分类Dev

将 2 个 preg_match_all 合并在一起

来自分类Dev

如何基于主键将两个序列合并在一起?

Related 相关文章

热门标签

归档