2017-02-17 2 views
1

J'utilise SQL dans Cognos. Si j'ai une colonne de dates et de champs d'intérêt, comment puis-je créer une nouvelle colonne où la valeur différente la plus récente est avancée pour chaque ligne. Je ne crois pas que je puisse utiliser le décalage pour le faire. Merci pour vos idées.SQL Nouvelle colonne avec la plus récente valeur différente dans une colonne d'intérêt

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 

Répondre

0

Ceci est juste une idée rapide qui a traversé l'esprit.

Si vous pouviez ajouter deux colonnes (ne pas les afficher les utiliser seulement pour la logique) ainsi:

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

Par conséquent, vous pouvez utiliser la fonction CASE pour tester nombre et attribuer des lettres.

0

Vue d'ensemble

L'essentiel de la solution est une approche en 2 étapes. D'abord, considérons les enregistrements d'origine classés selon Date et les enregistrements consécutifs avec la même valeur Field étant groupés, en notant les dates maximale et minimale de chacun desdits groupes. Les enregistrements de l'ensemble de résultats généré décrivent les intervalles de date maximaux dans lesquels la valeur du champ ne change pas (cette sélection est encapsulée dans la vue vtest_lag dans l'exemple sql ci-dessous)

Ensuite, rejoignez ce nouveau résultat avec un décalage de 1 sur l'une de sa colonne date. de cette façon, les intervalles adjacents sont jumelés dans le resultset finale, ce qui permet de mettre à jour Field valeurs comme vous le souhaitez.

Avertissements

  1. la solution suppose aucune date double dans les données d'origine
  2. La solution ne porte pas sur l'efficacité

solution SQL

Cet exemple autonome est agnostique aux dialectes sql en dehors de rownum pseudo-colonne Oracle fournissant le nombre ordinal d'un enregistrement dans un jeu de résultats. Il existe des fonctionnalités équivalentes dans d'autres arômes sql.

Partie 1/2: Configuration

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

Partie 2/2: Mise à jour

Voir vtest_lag encapsule la requête pour fournir les données de la déclaration de mise à jour.

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

Merci. Mes données sont plus compliquées et incluent des dates répétées, avec un autre champ de séquence. Je vais examiner votre réponse et l'apprécier grandement. Comme il ne voit pas comme une solution compacte existe, je peux importer les données à R où je peux faire la manipulation facilement en utilisant: – Patrick

+0

out.i <- list ("vector") pour (i dans 1: nrow (dat)) { pour (j dans 1: nrow (dat)) { if ((dat [i, 2] == dat [ max (i, j), 2]) == FAUX) { out.i [[i]] <- data.frame (date [i,], dat [max (i, j), 2]) pause } else { out.I [[i]] <- data.frame (dat [i,], dat [max (i, j), 2])} }} outi <- do .call (rbind, out.i) colnames (outi) [3] <- "FieldNew" outi [3] <- ifelse (outi [, 2] == outi [, 3], "", as.character (outi [, 3])) – Patrick