2016-11-28 76 views
5

Kullanıcılarımızın, iPad uygulamasında bir tablo üzerinde yaptıkları işlemlerin ana akışlarını günlüğe kaydediyoruz. Her bir akışın bir başlangıç ​​(etiketli Başlangıç) ve İptal Edilen veya Bitirilmiş bir ucu vardır ve herhangi bir örtüşen olay olmamalıdır.Postgresql'de Sıralı Olayların Eşleştirilmesi

bir kullanıcı için Başlatılan İptal veya Biten akışlarının kümesi aşağıdaki gibidir:

user_id    timestamp     event_text  event_num 
[email protected] 2016-10-30 00:08:00.966+00 Flow Started 0 
[email protected] 2016-10-30 00:08:15.58+00 Flow Cancelled 2 
[email protected] 2016-10-30 00:08:15.581+00 Flow Started 0 
[email protected] 2016-10-30 00:34:44.134+00 Flow Finished 1 
[email protected] 2016-10-30 00:42:26.102+00 Flow Started 0 
[email protected] 2016-10-30 00:42:49.276+00 Flow Cancelled 2 
[email protected] 2016-10-30 00:42:49.277+00 Flow Started 0 
[email protected] 2016-10-30 00:59:47.337+00 Flow Cancelled 2 
[email protected] 2016-10-30 00:59:47.337+00 Flow Started 0 
[email protected] 2016-10-30 00:59:47.928+00 Flow Cancelled 2 

Biz ne kadar iptal edilen ve bitmiş akışına son ortalama hesaplamak istiyorum. Bunun için İptal Edilen veya Tamamlanmış ile başlatılan etkinliği eşleştirmeliyiz. Flow1 (süregelen akışını sonlandırmadan önce

bir müşteri yeni akışını başlatmak istiyor
  • (en Flow2 diyelim): Aşağıdaki kod ancak elimizdeki aşağıdaki veri kalitesi soruna geçici edemez gelmez ki), yeni akış için başlatılan etkinliği çekerken iptal edilmiş bir etkinlik çekiyoruz. Yani Flow1 Cancelled=Flow2 Started. Ancak, aslında farklı akışlara ait olan sıralı olaylar arasında sıralamak/yönlendirmek/yönlendirmek için pencere işlevlerini kullandığımızda. Bu kodu kullanarak :

    WITH track_scf AS (SELECT user_id, timestamp, event_text, CASE WHEN event_text LIKE '%Started%' THEN 0 when event_text like '%Cancelled%' then 2 ELSE 1 END AS event_num FROM tracks ORDER BY 2, 4 desc) SELECT user_id, CASE WHEN event_num=0 then timestamp end as start,CASE WHEN LEAD(event_num, 1) OVER (PARTITION BY user_id ORDER BY timestamp,event_num) <> 0 THEN LEAD(timestamp, 1) OVER (PARTITION BY user_id ORDER BY timestamp,event_num) END as end, CASE WHEN LEAD(event_num, 1) OVER (PARTITION BY user_id ORDER BY timestamp,event_num) <> 0 THEN LEAD(event_num, 1) OVER (PARTITION BY user_id ORDER BY timestamp,event_num) END as action FROM track_scf 
    

Bu sonuç almak:

user_id    start      end       action 
[email protected] 2016-10-30 00:08:00.966+00 2016-10-30 00:08:15.58+00 2 
[email protected] 2016-10-30 00:08:15.581+00 2016-10-30 00:34:44.134+00 1 
[email protected] 2016-10-30 00:42:26.102+00 2016-10-30 00:42:49.276+00 2 
[email protected] 2016-10-30 00:42:49.277+00 NULL      NULL 
[email protected] 2016-10-30 00:59:47.337+00 2016-10-30 00:59:47.337+00 2 
[email protected] NULL      2016-10-30 00:59:47.928+00 2 

Ama biz bu almalısınız: Öyle kodu değiştiremez gerekiyor Nasıl

user_id    start      end       action 
[email protected] 2016-10-30 00:08:00.966+00 2016-10-30 00:08:15.58+00 2 
[email protected] 2016-10-30 00:08:15.581+00 2016-10-30 00:34:44.134+00 1 
[email protected] 2016-10-30 00:42:26.102+00 2016-10-30 00:42:49.276+00 2 
[email protected] 2016-10-30 00:42:49.277+00 2016-10-30 00:59:47.337+00 2 
[email protected] 2016-10-30 00:59:47.337+00 2016-10-30 00:59:47.928+00 2 

eşleştirme doğru mu?

cevap

2
select  user_id  
      ,"start"      
      ,"end"       
      ,"action" 

from  (select  user_id 
         ,timestamp     as "start" 
         ,lead (event_num) over w as "action" 
         ,lead ("timestamp") over w as "end" 
         ,event_num 

      from  tracks t 

      window  w as (partition by user_id order by "timestamp",event_num desc) 
      ) t 

where  t.event_num = 0 
; 
+0

Çalışıyor! Oldukça şık bir çözüm ... teşekkürler! –