Sql 修复并缩小不正确的历史记录

Sql 修复并缩小不正确的历史记录,sql,teradata,Sql,Teradata,我必须为收缩错误的历史数据编写SQL,如下所示: K1 K2 D1 D2 start_date End_date 1 2 A B 04-08-2018 05-08-2018 1 2 A B 05-08-2018 06-08-2018 1 2 A B 06-08-2018 08-08-2018 3 4 P Q 04-08-2018 05-

我必须为收缩错误的历史数据编写SQL,如下所示:

      K1   K2   D1  D2  start_date  End_date
       1    2   A   B   04-08-2018  05-08-2018
       1    2   A   B   05-08-2018  06-08-2018
       1    2   A   B   06-08-2018  08-08-2018
       3    4   P   Q   04-08-2018  05-08-2018
       3    4   P   Q   05-08-2018  06-08-2018
       3    4   P   Q   06-08-2018  31-12-2018
       1    2   C   D   04-08-2018  05-08-2018
       1    2   C   D   05-08-2018  06-08-2018
       1    2   C   D   06-08-2018  31-12-2018
       1    2   A   B   08-08-2018  09-08-2018
       1    2   A   B   09-08-2018  10-08-2018
       1    2   A   B   10-08-2018  31-12-2018
其中K1和K2是我的关键列。 由于某些原因,我有重复的历史数据,需要修复,但必须保持记录的出现。 在这里,我必须将连续的历史合并为一个,输出如下

      K1    K2  D1  D2  start_date  end_date
       1    2   A   B   04-08-2018  08-08-2018
       3    4   P   Q   04-08-2018  31-12-2018
       1    2   C   D   04-08-2018  31-12-2018
       1    2   A   B   08-08-2018  31-12-2018

请忽略未来日期,这只是为了取样。

我认为可以忽略结束日期,因此这是一个简单的差距和孤岛问题:

select k1, k2, d1, d2,
       min(start_date), max(end_date)
from (select t.*,
             row_number() over (partition by k1, k2 order by start_date) as seqnum,
             row_number() over (partition by k1, k2, d1, d2 order by start_date) as seqnum_2
      from t
     ) t
group by k1, k2, d1, d2, (seqnum - seqnum_2);

我认为可以忽略结束日期,因此这是一个简单的缺口和孤岛问题:

select k1, k2, d1, d2,
       min(start_date), max(end_date)
from (select t.*,
             row_number() over (partition by k1, k2 order by start_date) as seqnum,
             row_number() over (partition by k1, k2, d1, d2 order by start_date) as seqnum_2
      from t
     ) t
group by k1, k2, d1, d2, (seqnum - seqnum_2);

下面将解决您的问题:

SELECT K1,K2,D1,D2,
       -- THIS SPLITS THE PERIOD BACK TO SEPERATE COLUMNS 
       BEGIN(PD) AS START_DT, NULLIF(END(PD), DATE '9999-12-31') AS END_DT
    FROM
    ( 
       SELECT NORMALIZE -- THIS RETURNS YOUR NORMALIZED RESULT AS A PERIOD
          K1,K2,D1,D2,
          PERIOD(START_DT,COALESCE(END_DT, DATE '9999-12-31')) AS PD
       FROM TEST2  WHERE START_DT < END_DT
    ) AS DT

下面将解决您的问题:

SELECT K1,K2,D1,D2,
       -- THIS SPLITS THE PERIOD BACK TO SEPERATE COLUMNS 
       BEGIN(PD) AS START_DT, NULLIF(END(PD), DATE '9999-12-31') AS END_DT
    FROM
    ( 
       SELECT NORMALIZE -- THIS RETURNS YOUR NORMALIZED RESULT AS A PERIOD
          K1,K2,D1,D2,
          PERIOD(START_DT,COALESCE(END_DT, DATE '9999-12-31')) AS PD
       FROM TEST2  WHERE START_DT < END_DT
    ) AS DT


为什么不投票,至少在评论中分享。不要滥用你的权利,我没有投反对票。SQL中没有连续行这样的东西。除非有其他数据可供排序,否则无法保持1、2、A、B这两组数据的不同。如果有另一列,则需要查找间隙和孤岛并分组。用正在使用的数据库标记问题。为什么在结果中保留两个不同的行1、2、A、B???您需要了解数据库表没有任何行顺序。因此,没有一行出现在其他两行之间。关于这些行,唯一重要的是里面有什么。除非您了解到这一点,否则您肯定会继续以错误的方式使用SQL技术。@ErwinSmout我知道SQL没有行排序,我只是指数据加载wrt start_date中的间隙,而不是它的排序。不管怎样,我们已经创建了SQL并修复了数据。为什么不投票,至少在评论中共享它呢。不要滥用你的权利,我没有投反对票。SQL中没有连续行这样的东西。除非有其他数据可供排序,否则无法保持1、2、A、B这两组数据的不同。如果有另一列,则需要查找间隙和孤岛并分组。用正在使用的数据库标记问题。为什么在结果中保留两个不同的行1、2、A、B???您需要了解数据库表没有任何行顺序。因此,没有一行出现在其他两行之间。关于这些行,唯一重要的是里面有什么。除非您了解到这一点,否则您肯定会继续以错误的方式使用SQL技术。@ErwinSmout我知道SQL没有行排序,我只是指数据加载wrt start_date中的间隙,而不是它的排序。不管怎样,我们已经创建了SQL并修复了数据。这真的符合要求吗?只是问,因为对我来说,它看起来可疑。抱歉忽视考虑unaskdt,但它保留了1,2,a,b,dt1,dt2和1,2,a,b,dt8,dt9,如果这些都是行吗?生成的行号在我看来似乎是1,1和2,2,所以第五个分组值在这两种情况下都是0,所以它们被分组在一起,得到一行dt1,dt9。@ErwinSmout。不,但OP的数据结构似乎不是这样的。在这种情况下,非常值得一提的是,所有关于漏洞和孤岛的假设,因为如果OP没有明确确认其中任何一个,那么实际上就不需要你开始制作它们了……这真的符合要求吗?只是问,因为对我来说,它看起来可疑。抱歉忽视考虑unaskdt,但它保留了1,2,a,b,dt1,dt2和1,2,a,b,dt8,dt9,如果这些都是行吗?生成的行号在我看来似乎是1,1和2,2,所以第五个分组值在这两种情况下都是0,所以它们被分组在一起,得到一行dt1,dt9。@ErwinSmout。不,但OP的数据结构似乎不是这样的。在这种情况下,非常值得一提的是,所有关于漏洞和孤岛的假设,因为如果OP没有明确确认这些假设中的任何一个,那么实际上就不需要你开始做这些假设了。。。