2017-02-17 33 views
1

Я использую SQL в 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 

ответ

0

Это просто быстрая идея, которая пересекла разум.

Если бы вы могли добавить две колонки (не отображать их просто использовать их для логики) таким образом:

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

Таким образом, вы можете использовать функцию СЛУЧАЙ, чтобы проверить номер и присвоить буквы.

0

Обзор

Суть решения является 2-ступенчатый подход.

Сначала учтите первоначальные записи, упорядоченные в соответствии с Date, и последовательные записи с тем же значением Field, сгруппированным, отмечая максимальные и минимальные даты каждой из указанных групп. В записях сгенерированных результирующих данных указаны максимальные интервалы дат, в пределах которых значение поля не изменяется (этот выбор инкапсулирован в виде vtest_lag в примере ниже).

Далее присоединитесь к этому новому набору результатов с запаздыванием 1 на одной из его даты столбца. Таким образом, примыкающие интервалы спарены в окончательном результирующем, что позволяет обновлять Field значения по желанию.

Предостережения

  1. решение не принимает на себя никаких дубликатов даты в исходных данных
  2. Решение не связана с эффективностью

SQL-раствор

Этот автономный пример агностиком к SQL диалектов помимо 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: Обновление

Посмотреть 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) 
     ; 
+0

спасибо. Мои данные более сложны и включают повторяющиеся даты с другим полем последовательности. Я просмотрю ваш ответ, хотя и очень ценю это. Поскольку он не видит, как существует компактное решение, я могу импортировать данные в R, где я могу легко манипулировать с помощью: – Patrick

+0

.i <- list ("vector") для (i in 1: nrow (dat)) { для (j in 1: nrow (dat)) { if ((dat [i, 2] == dat [ max (i, j), 2]) == FALSE) { out.i [[i]] <- data.frame (dat [i,], dat [max (i, j), 2]) break } еще { out.I [[I]] <- data.frame (DAT [я,], DAT [макс (I, J), 2]) } } } Outi <- делать .call (rbind, out.i) colnames (outi) [3] <- "FieldNew" outi [3] <- ifelse (outi [, 2] == outi [, 3], "", as.character (Outi [3])) – Patrick