2017-02-17 5 views
1

私はCognosでSQLを使用しています。 日付と関心の列がある場合、最新の異なる値が各行に表示される新しい列を作成するにはどうすればよいですか。私はこれを行うためにラグを使うことができるとは思わない。アイデアありがとうございます。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 

答えて

0

これは、頭が狂った簡単なアイデアです。

次の2つの列(単にロジックのためにそれらを使用して表示されません)このよう追加することができた場合:したがって

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

を、あなたは数をテストし、文字を割り当てるには、関数CASEを使用することができます。

0

概要

溶液の要旨は、2段階のアプローチです。

最初に、Dateに基づいて注文された元のレコードと、同じグループの最大日付と最小日付を示す同じField値を持つ連続するレコードを考慮してください。生成された結果セットのレコードには、フィールド値が変更されない最大の日付間隔が記述されます(この選択は、以下のSQLの例のvtest_lagビューにカプセル化されています)。

次に、この新しい結果セットを1のラグその日付列のいずれか。このように、隣接する間隔は所望のようField値を更新することができ、最終的な結果セットに対になっている。

警告

  1. は、溶液は、元のデータには重複日付を前提としない
  2. 溶液を離れ、結果セット内のレコードの序数を供給オラクルrownum疑似から効率

SQL溶液

この自己完結型の例は、SQLダイアレクトにとらわれないと関係しません。他の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:更新

ビューvtest_lagは、UPDATE文のためのデータを提供するクエリをカプセル化します。

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) 
     ; 
+0

ありがとうございます。私のデータはより複雑で、繰り返しの日付も含まれ、別のシーケンスフィールドもあります。私はあなたの答えを見て、それを大いに感謝します。コンパクトなソリューションが存在するようには見えないので、データをRにインポートすると、簡単に操作できます: – Patrick

+0

out。(dat [i、2] == dat [0:0]の場合)[ の場合、{iは1:nrow(dat)}のための のための{ のために、 (i、j)、2]) out.i [[i]] < - data.frame(dat [i、j)、2])= }他{ out.i [[I] < - data.frame(DAT [I、]、DAT [MAX(i、j)は、2])} }} OUTI < - DO Outl [3] < - ifelse(outi [、2] == outi [、3]、 ""、as.character).call(rbind、out.i) colnames(outi)[3] < - "FieldNew" outi [3] (outi [、3])) – Patrick

関連する問題