SQL新列,在感兴趣的列中具有最新的不同值

时间:2017-02-17 16:52:09

标签: sql lag difference

我在Cognos中使用SQL。 如果我有一列日期和感兴趣的字段,我如何创建一个新列,其中每行提供最新的不同值。我不相信我可以用滞后来做这件事。谢谢你的任何想法。

Example:
    Date    Field   DesiredNew 
    1/9/1994    D   C
    1/8/1994    D   C
    1/7/1994    D   C
    1/6/1994    C   B
    1/5/1994    B   A
    1/4/1994    B   A
    1/3/1994    B   A
    1/2/1994    A   
    1/1/1994    A   

2 个答案:

答案 0 :(得分:0)

这只是一个思维敏捷的快速想法。

如果您可以添加两列(不显示它们只是将它们用于逻辑):

Date    Field   DesiredNew FieldSeq DesicredNewSeq
1/7/1994    D   C          4        3
1/6/1994    C   B          3        2

因此,您可以使用函数CASE来测试数字和分配字母。

答案 1 :(得分:0)

<强>概述

解决方案的要点是两步法。

首先,考虑根据Date排序的原始记录和具有相同Field值的连续记录,并记录每个所述组的最大和最小日期。生成的结果集记录描述了字段值不变的最大日期间隔(此选择封装在下面的sql示例中的视图vtest_lag中)。

接下来自我加入这个新结果集,其日期列之一的延迟为1。这样,相邻区间在最终结果集中配对,允许根据需要更新Field值。

<强>注意事项

  1. 解决方案假设原始数据中没有重复日期
  2. 解决方案与效率无关
  3. SQL解决方案

    这个独立的示例与sql方言无关,除了oracle的rownum伪列,提供结果集中记录的序号。其他sql风格也有相同的功能。

    第1/2部分:设置

    create table test_lag (
        t_date        date
      , field         varchar2(10)
      , desirednew    varchar2(10)
      , computednew   varchar2(10)
    );
    
    insert into test_lag values ( to_date ( '01/09/1994', 'DD/MM/YYYY' ), 'D', 'C'  , null );
    insert into test_lag values ( to_date ( '01/08/1994', 'DD/MM/YYYY' ), 'D', 'C'  , null );
    insert into test_lag values ( to_date ( '01/07/1994', 'DD/MM/YYYY' ), 'D', 'C'  , null );
    insert into test_lag values ( to_date ( '01/06/1994', 'DD/MM/YYYY' ), 'C', 'B'  , null );
    insert into test_lag values ( to_date ( '01/05/1994', 'DD/MM/YYYY' ), 'B', 'A'  , null );
    insert into test_lag values ( to_date ( '01/04/1994', 'DD/MM/YYYY' ), 'B', 'A'  , null );
    insert into test_lag values ( to_date ( '01/03/1994', 'DD/MM/YYYY' ), 'B', 'A'  , null );
    insert into test_lag values ( to_date ( '01/02/1994', 'DD/MM/YYYY' ), 'A', null , null );
    insert into test_lag values ( to_date ( '01/01/1994', 'DD/MM/YYYY' ), 'A', null , null );
    

    第2/2部分:更新

    View vtest_lag封装查询以提供更新语句的数据。

      create or replace view vtest_lag as
      select emb.*
           , rownum seq
        from (
                  select *
                    from (
                              select sysdate    t_date1
                                   , null       field1
                                   , t_date     t_date2
                                   , field      field2
                                from test_lag
                               where t_date = (select max(t_date) from test_lag)
                           union all
                              select t_date     t_date1
                                   , field      field1
                                   , to_date( '01/01/1900', 'DD/MM/YYYY' )
                                                t_date2
                                   , null       field2
                                from test_lag
                               where t_date = (select min(t_date) from test_lag)
                           union all
                              select po1.t_date    t_date1
                                   , po1.field     field1
                                   , po2.t_date    t_date2
                                   , po2.field     field2
                                from (
                                       select po1_base.*
                                            , rownum    seq
                                         from (
                                                   select *
                                                     from test_lag
                                                 order by t_date desc
                                              ) po1_base
                                     ) po1
                                join (
                                       select po2_base.*
                                            , rownum     seq
                                         from (
                                                   select *
                                                     from test_lag
                                                 order by t_date desc
                                              ) po2_base
                                     ) po2
                                  on po2.seq = po1.seq + 1
                               where po1.field <> po2.field
                         )
                order by t_date1 desc
             ) emb
             ;
    
      update test_lag trg
         set trg.computednew = (select v2.field2 from vtest_lag v1 join vtest_lag v2 on v2.seq = v1.seq+1 where trg.t_date <= v1.t_date2 and trg.t_date >= v2.t_date1)
           ;