暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 将两行合并成一行

ASKTOM 2019-04-12
876

问题描述

嗨,汤姆,

我寻求你的帮助,如何比较表中的两行,如果它们是相同的合并行。

create table test(id number, start_date date, end_date date, col1 varchar2(10), col2 varchar2(10), col3 varchar2(10));

insert into test values(1, to_date('01/01/1900', 'mm/dd/yyyy'), to_date('05/01/2006', 'mm/dd/yyyy'), 'a', 'b', 'a');

insert into test values(1, to_date('05/02/2006', 'mm/dd/yyyy'), to_date('06/01/2006', 'mm/dd/yyyy'), 'x', 'y', 'z');

insert into test values(1, to_date('07/01/2006', 'mm/dd/yyyy'), to_date('07/01/2016', 'mm/dd/yyyy'), 'x', 'y', 'z');

insert into test values(1, to_date('08/01/2016', 'mm/dd/yyyy'), to_date('09/01/2016', 'mm/dd/yyyy'), 'x', 'b', 'a');

insert into test values(1, to_date('10/01/2016', 'mm/dd/yyyy'), to_date('12/31/2020', 'mm/dd/yyyy'), 'a', 'b', 'a');
复制


数据集将是

id             start date        end date       col1    col2   col3
1              01/01/1900         05/01/2006     a        b     c
1              05/02/2006         06/01/2006     x        y     z  ------ record 2
1              07/01/2006         07/01/2016     x        y     z  ------ record 3  
1              08/01/2016         09/01/2016     x        b     a
1              10/01/2016         12/31/2016     a        b     c 
复制


如您所见,记录2和记录3列1、2、3值相同。这些记录需要合并为1条记录,其中最小开始日期为记录2,最大结束日期为记录3。

预期结果集如下

id      start date    end date    col1    col2   col3
1       01/01/1900    05/01/2006  a        b     c
1       05/02/2006*   07/01/2016* x        y     z  ------ 2 and 3 merged with min and max dates
1       08/01/2016    09/01/2016  x        b     a
1       10/01/2016    12/31/2016  a        b     c 
复制


我们如何在sql语句中实现这一点。

非常感谢您的帮助。

提前谢谢。

专家解答

我不清楚您如何确切地定义要分组的X,Y,Z行,而不是A,B,C行。是在上一个结束和下一个开始之间有一个月的时间吗?

你需要明确这个匹配是如何工作的,以获得一个完整的解决方案。

但无论如何:

模式匹配 (匹配 _ 识别) 到救援!

使用它来定义一个模式变量,该变量提供了合并行的标准。如果结束日期和开始日期之间正好有一个月,我已经假设您将它们组合在一起。根据需要对您的数据进行调整。

然后,这只是搜索后面有这个变量的任何行的问题。同样,我假设有许多连续的行要合并它们。如果不是这种情况,请将正则表达式量词从匹配任意行数 (*/星号) 更改为零到N。例如,如果要合并最多两行,请使用以下模式:

strt consecutive{0,1}
复制


所有这些都给出了:

select * 
from   test match_recognize (
  partition by id, col1, col2, col3
  order by start_date
  measures
    first ( start_date ) as st,
    last ( end_date ) as en
  pattern ( strt consecutive* ) 
  define
    consecutive as 
      start_date = add_months ( 
                     prev ( end_date ), 1 
                   )
)
order  by st, en;

ID   COL1   COL2   COL3   ST                     EN                     
   1 a      b      a      01-JAN-1900 00:00:00   01-MAY-2006 00:00:00   
   1 x      y      z      02-MAY-2006 00:00:00   01-JUL-2016 00:00:00   
   1 x      b      a      01-AUG-2016 00:00:00   01-SEP-2016 00:00:00   
   1 a      b      a      01-OCT-2016 00:00:00   31-DEC-2020 00:00:00 
复制


Stew Ashton在以下位置更详细地讨论了合并连续日期范围的挑战:https://stewashton.wordpress.com/2014/03/16/merging-contiguous-date-ranges/

如果你正在寻找更多关于模式匹配的背景,你可以在我的答案中找到更多的例子:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:9533477800346658909

或者我关于这个主题的幻灯片:https://www.slideshare.net/ChrisSaxon1/how-to-find-patterns-in-your-data-with-sql
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论