2017-08-07 2 views
0

je la sortie suivante:groupe SQL par et la fonction Lag ne pas donner une sortie correcte

last_login     | id | type | w_id 
    11/9/2016 10:59:13 PM | 123 | Thing1 | W1 
    11/9/2016 10:59:15 PM | 123 | Thing1 | W1 
    11/9/2016 10:59:15 PM | 123 | Thing1 | W3 
    11/10/2016 10:59:13 PM | 123 | Thing2 | W2 
    11/11/2016 10:59:13 PM | 123 | Thing1 | W1 
    11/12/2016 10:59:13 PM | 123 | Thing1 | W1 
    11/12/2016 10:59:13 PM | 345 | Thing1 | W4 
    11/13/2016 10:59:13 PM | 345 | Thing1 | W1 
    11/14/2016 10:59:13 PM | 345 | Thing2 | W2 
    11/15/2016 10:59:13 PM | 345 | Thing2 | W5 
    11/16/2016 10:59:13 PM | 345 | Thing1 | W1 
    11/16/2016 10:59:13 PM | 345 | Thing1 | W1 
    11/17/2016 10:59:13 PM | 345 | Thing1 | W4 
    11/17/2016 10:59:13 PM | 345 | Thing1 | W4 

pour la requête ci-dessous:

select sa.last_login, ad.ID, sa.type, w_id, 
from table1 dcc 
join table2 AD 
on AD.ID=DCC.id 

JOIN table3 sa 
ON AD.ID=sa.id 
join table4 sc 
on dcc.id=sc.id 
where sic3=‘Something’ 
order by dcc.id, sa.last_login 

Je veux une sortie de quelque chose comme ceci:

last_login    | id | old_type | type | old_w_id | w_id 
11/11/2016 10:59:13 PM | 123 | Thing2 | Thing1 | W2  | W1 
11/17/2016 10:59:13 PM | 345 | Thing1 | Thing1 | W1  | W4 

Je suis en train de le faire de la manière suivante:

select 

t.last_login, t.id, t.old_type, t.type , t.old_w_id, t.w_id 

from 

(select sa.last_login, ad.id, sa.type, 
lag(sa.type, 1) over (partition by ad.id order by sa.last_login) as old_type, w_id, 
lag(w_id, 1) over (partition by ad.ID order by sa.last_login) as old_w_id from table1 dcc 

join table2 AD 
on ad.id=DCC.id 

JOIN table3 sa 
ON AD.ID=sa.id 

join table4 sc 
on dcc.id=sc.id 

where sc.si=’Something’ 
order by dcc.id, sa.last_login) t 

where t.old_type like ’THING1’ and t.type like ‘THING2’ 

group by t.id, t.id, t.old_type, t.type, t.w_id, t.old_w_id 

Mais je reçois une sortie de quelque chose comme ceci:

last_login    | id | old_type | type | old_w_id | w_id 
11/11/2016 10:59:13 PM | 123 | Thing1 | Thing2 | W1  | W2 

Comment puis-je obtenir la sortie désirée et pourquoi ma requête (fonction de décalage) ne fonctionne pas correctement?

+0

Qu'est-ce que le groupe 'by' a à voir avec cette requête? –

+0

C'est une énorme table avec plusieurs entrées par identifiant. – akrama81

+0

@GordonLinoff Edité la sortie de la table et la sortie requise dans ma question pour obtenir une meilleure idée – akrama81

Répondre

0

Vous n'avez pas besoin d'une sous-requête pour cela. Il suffit d'utiliser lag():

select sa.last_login, ad.ID, sa.type, w_id, 
     lag(sa.type) over (partition by ad.id order by sa.last_login) as prev_type, 
     lag(sa.w_id) over (partition by ad.id order by sa.last_login) as prev_w_id 
from table1 dcc join 
    table2 AD 
    on AD.ID = DCC.id join 
    table3 sa 
    on AD.ID = sa.id join 
    table4 sc 
    on dcc.id = sc.id 
where sic3 = 'Something' 
order by dcc.id, sa.last_login 

Si vous voulez juste la dernière ligne, vous pouvez utiliser fetch first 1 row only ou sometihng comme:

select * 
from (select sa.last_login, ad.ID, sa.type, w_id, 
      lag(sa.type) over (partition by ad.id order by sa.last_login) as prev_type, 
      lag(sa.w_id) over (partition by ad.id order by sa.last_login) as prev_w_id, 
      row_number() over (partition by ad.id order by sa.last_login desc) as seqnum 
     from table1 dcc join 
      table2 AD 
      on AD.ID = DCC.id join 
      table3 sa 
      on AD.ID = sa.id join 
      table4 sc 
      on dcc.id = sc.id 
     where sic3 = 'Something' 
    ) t 
where seqnum = 1 
order by id, last_login; 
+0

Non, je n'ai pas besoin seulement de la dernière rangée, car comme indiqué dans mon exemple ci-dessus (pour l'ID 123) les deux dernières lignes sont Thing1, Thing1 & W1, W1, cependant je veux Thing1, Thing2 & W1, W2. Je veux quand la dernière fois il y avait un changement de type ou w_id. – akrama81

0

Après avoir fait un retard sur les champs que vous souhaitez vérifier (type et W_ID) , vous pouvez juste envelopper dans une autre instruction select avec une clause where qui supprime les lignes où la dernière est égale à la précédente. Par exemple:

EDIT Ma première réponse incluait toutes les lignes où elle venait juste de changer, tout ce que j'ai fait était de prendre ce code et de l'emballer pour saisir les changements les plus importants partitionnés par l'ID.

create table Testing 
(
    last_login date, 
    id number, 
    type varchar2(50), 
    w_id varchar2(2) 
); 

insert into Testing values(to_date('11/09/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),123,'Thing1','W1'); 
insert into Testing values(to_date('11/09/2016 10:59:15 PM','MM/DD/YYYY HH:MI:SS PM'),123,'Thing1','W1'); 
insert into Testing values(to_date('11/09/2016 10:59:15 PM','MM/DD/YYYY HH:MI:SS PM'),123,'Thing1','W3'); 
insert into Testing values(to_date('11/10/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),123,'Thing2','W2'); 
insert into Testing values(to_date('11/11/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),123,'Thing1','W1'); 
insert into Testing values(to_date('11/12/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),123,'Thing1','W1'); 
insert into Testing values(to_date('11/12/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing1','W4'); 
insert into Testing values(to_date('11/13/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing1','W1'); 
insert into Testing values(to_date('11/14/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing2','W2'); 
insert into Testing values(to_date('11/15/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing2','W5'); 
insert into Testing values(to_date('11/16/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing1','W1'); 
insert into Testing values(to_date('11/16/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing1','W1'); 
insert into Testing values(to_date('11/17/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing1','W4'); 
insert into Testing values(to_date('11/17/2016 10:59:13 PM','MM/DD/YYYY HH:MI:SS PM'),345,'Thing1','W4'); 

select LAST_LOGIN, ID, TYPE, W_ID, TypeLag, W_IDLag 
from(
select LAST_LOGIN, ID, TYPE, W_ID, TypeLag, W_IDLag, 
     rank() over(partition by id order by last_login desc) RankOrder 
from(
select Testing.*, 
     lag(TYPE,1) over(partition by ID order by last_login) TypeLag, 
     lag(W_ID,1) over(partition by ID order by last_login) W_IDLag 
from Testing) 
where (nvl(TypeLag,'X') <> TYPE 
    or nvl(W_IDLag,'X') <> W_ID) 
) 
where RankOrder = 1 

sortie est:

LAST_LOGIN ID  TYPE W_ID TYPELAG  W_IDLAG 
11-NOV-16 123  Thing1 W1  Thing2  W2 
17-NOV-16 345  Thing1 W4  Thing1  W1 
+0

Cela ne donne pas la sortie attendue pour l'ID 345 – akrama81

+0

Cela donne toutes les lignes où un changement vient de se produire. En relisant votre question, voulez-vous juste 1 ligne par ID? –

+0

Oui, j'ai montré le résultat attendu dans ma question – akrama81