8
votes

Comment puis-je trouver des valeurs consécutives en double dans ce tableau?

dise que j'ai une table que j'interrète comme si: xxx

et cela me donne des résultats: xxx

Je suis intéressé Dans les lignes de ce résultat défini dans lesquelles la valeur est identique à celle de la rangée précédente ou suivante, comme la rangée B qui a une valeur = 2 la même chose que la rangée a. Je m'en fiche des rangées comme la rangée C qui a une valeur = 2 mais ne vient pas directement après une ligne avec valeur = 2. Comment puis-je interroger la table pour me donner toutes les lignes comme A et B seulement? Ceci est sur Oracle, si cela compte.


2 commentaires

Y a-t-il d'autres champs dans la table, par exemple une clé primaire séquentielle? Cela faciliterait la tâche! Est-ce une table de transaction ou peut-on supprimer (c'est-à-dire des jointures et des tests avec ID-1 ou ID + 1)?


@Kieren Oui, il y a une clé primaire, mais elles sont distribuées dans un ordre incompatible avec le champ Date. Je ne sais pas ce que vous avez l'intention de "jointures et tests", mais oui, les enregistrements sont supprimés et remplacés assez souvent.


3 Réponses :


12
votes

Utilisez les fonctions analytiques de plomb et de lag.

create table t3 (d number, v number);
insert into t3(d, v) values(1, 1);
insert into t3(d, v) values(2, 2);
insert into t3(d, v) values(3, 2);
insert into t3(d, v) values(4, 3);
insert into t3(d, v) values(5, 2);
insert into t3(d, v) values(6, 3);
insert into t3(d, v) values(7, 4);

select d, v, case when v in (prev, next) then '*' end match, prev, next from (
  select
    d,
    v,
    lag(v, 1) over (order by d) prev,
    lead(v, 1) over (order by d) next
  from
    t3
)
order by
  d
;


1 commentaires

Pourquoi avez-vous commander par d lorsque les données sont déjà commandées par D par vos inserts? En outre, le problème initial ne semblait pas avoir besoin de tri pour exécuter correctement.



1
votes

Alors que @janek Bogucuki a souligné le plomb et le décalage est probablement le moyen le plus simple d'accomplir cela - mais juste pour le plaisir essayez de le faire en utilisant uniquement les opérations de jointure de base:

SELECT mydate, VALUE FROM
  (SELECT a.mydate, a.value,
          CASE WHEN a.value = b.value THEN '*' ELSE NULL END AS flag1,
          CASE WHEN a.value = c.value THEN '*' ELSE NULL END AS flag2
     FROM
       (SELECT ROWNUM AS outer_rownum, mydate, VALUE
         FROM mytable
         ORDER BY mydate) a
     LEFT OUTER JOIN
       (select ROWNUM-1 AS inner_rownum, mydate, VALUE
         from mytable
         order by myDATE) b
       ON b.inner_rownum = a.outer_rownum
     LEFT OUTER JOIN
       (select ROWNUM+1 AS inner_rownum, mydate, VALUE
         from mytable
         order by myDATE) c
       ON c.inner_rownum = a.outer_rownum
     ORDER BY a.mydate)
  WHERE flag1 = '*' OR
        flag2 = '*';


1 commentaires

ROWNUM est affecté avant le tri des résultats afin que cela ne soit pas garanti de fonctionner. Cela montre comment Row_Number () peut être utilisé à la place (pour obtenir une séquence ascendante de nombres correspondant à la commande par clause): Sélectionnez Rownum, Row_Number () sur (commander par V-D) à partir de la commande T3 par V-D; Cela utilise les données de ma réponse ci-dessus.



3
votes

Ceci est une version simplifiée de la réponse de @bob Jarvis, la principale différence étant l'utilisation d'une seule sous-requête au lieu de quatre, xxx


0 commentaires