2017-07-04 1 views
4

J'ai une exigence dans redshift où j'ai besoin de combiner le résultat si les données sont continues. J'ai le tableau suivant, où user_id, product_id sont varchar et login_time, log_out_time sont horodatage.Redshift requête pour combiner le résultat si les données sont continues dans un tableau

user_id product_id login_time    log_out_time 
---------------------------------------------------------------------- 
ashok  facebook  1/1/2017 1:00:00 AM  1/1/2017 2:00:00 AM 
ashok  facebook  1/1/2017 2:00:00 AM  1/1/2017 3:00:00 AM 
ashok  facebook  1/1/2017 3:00:00 AM  1/1/2017 4:00:00 AM 
ashok  linked_in 1/1/2017 5:00:00 AM  1/1/2017 6:00:00 AM 
ashok  linked_in 1/1/2017 6:00:00 AM  1/1/2017 7:00:00 AM 
ashok  facebook  1/1/2017 8:00:00 AM  1/1/2017 9:00:00 AM 
ram  facebook  1/1/2017 9:00:00 AM  1/1/2017 10:00:00 AM 
ashok  linked_in 1/1/2017 7:00:00 AM  1/1/2017 8:00:00 AM 

J'ai besoin de combiner le résultat si les données sont continues pour un user_id donné pour chaque produit. Donc, ma sortie devrait ressembler,

user_id product_id login_time    log_out_time 
---------------------------------------------------------------------- 
ashok  facebook  1/1/2017 1:00:00 AM  1/1/2017 4:00:00 AM 
ashok  facebook  1/1/2017 8:00:00 AM  1/1/2017 9:00:00 AM 
ashok  linked_in 1/1/2017 5:00:00 AM  1/1/2017 8:00:00 AM 
ram  facebook  1/1/2017 9:00:00 AM  1/1/2017 10:00:00 AM 

J'ai essayé avec la requête suivante, mais il ne me pas aidé,

SELECT user_id, product_id, MIN(login_time), MAX(log_out_time) FROM TABLE_NAME GROUP BY user_id, product_id 

Au-dessus de requête ne parvient pas à donner ma sortie nécessaire car il n'a pas la logique pour vérifier les données sont en temps continu. J'ai besoin d'une requête pour cela sans utiliser de fonction personnalisée, mais je suis autorisé à utiliser n'importe quelle fonction redshift intégrée.

Répondre

5

Vous pouvez utiliser lag() pour identifier où les groupes commencent, puis somme cumulative pour identifier les groupes, puis group by d'agréger les résultats:

select user_id, product_id, min(login_time), max(log_out_time) 
from (select t.*, 
      sum(case when prev_lt = login_time then 0 else 1 end) over 
       (partition by user_id, product_id 
        order by login_time 
        rows between unbounded preceding and current row 
       ) as grp 
     from (select t.*, 
        lag(log_out_time) over (partition by user_id, product_id order by login_time) as prev_lt 
      from t 
      ) t 
    ) t 
group by user_id, product_id, grp; 
+0

Votre requête ne donne pas la puissance requise. Si j'ai exécuté la requête ci-dessus, elle donne la même table source. J'ai juste échangé le 0 et le 1, dans ce cas il produit trois rangs mais ce n'est pas la sortie requise. Pour la ligne ashok & facebook j'ai une seule ligne comme 'ashok, facebook, 1/1/2017 1:00:00 AM, 1/1/2017 4:00:00 AM' mais la sortie requise est' ashok, facebook, 01/01/2017 01:00:00, 01/01/2017 04:00:00, \ n ashok, facebook, 1/1/2017 8:00:00, 1/1/2017 9:00 : 00 AM'. La sortie requise est disponible dans la question, veuillez jeter un oeil. – ashokramcse

+1

@ashokramcse. . . J'ai eu les heures de connexion/déconnexion inversées. La requête doit comparer l'heure de connexion actuelle à l'heure de déconnexion précédente (ce qu'elle est en train de faire). –

+0

Yup votre réponse éditée résout mon mystère. BTW, vous êtes vraiment un génie !!! – ashokramcse