2016-04-29 58 views
0

我有一個表格,其中包含用戶活動的記錄,其中涵蓋了由開始和結束時間指示的跨度。我正在尋找前一天每單位時間內系統中活動用戶的數量。計算從開始和結束時間導出的每分鐘會話

最大會話長度是一個小時,並且它們不跨越小時邊界。會話可以結束,並在同一分鐘內開始新會話。

下面是查詢的一個精簡版:

with minutes AS (
    -- ignore this...it generates a day's worth of timestamps for each minute 
    -- it's hairy but is what I'm stuck with on redshift 
    select (dateadd(minute, -row_number() over (order by true), sysdate::date)) as minute 
     from seed_table limit 1440 
), 
sessions as (
    select sid, ts_start, ts_end 
    from user_sessions s 
    where ts_end >= sysdate::date-'1 day'::interval 
     and ts_start < sysdate::date 
) 
select m.minute, count(distinct(s.sid)) 
from minutes m 
left join sessions s on s.ts_end >= m.minute and s.ts_start < m.minute+'1 min'::interval 
group by 1 

我試圖避開那個討厭左連接:

-> XN Nested Loop Left Join DS_BCAST_INNER (cost=6913826151.95..4727012848741.55 rows=410434560 width=166) 
    Join Filter: (("inner".ts_start < ("outer"."minute" + '00:01:00'::interval)) AND ("inner".ts_end >= "outer"."minute")) 

下面是基於戈登·利諾夫的答案是什麼,幾乎爲我工作。當用戶的會話在一分鐘之內轉換時,它就會被計算在內。看起來像正確的方向。原來的查詢可能會因爲同樣的原因而計算在內,但有機會在一分鐘內獲得不同會話ID的計數來解決這個問題。

select minute, sum(count) over (order by minute rows unbounded preceding) as users 
from (
    select minute, sum(count) as count 
    from (
     (
      select date_trunc('minute', ts_start) as minute, count(*) as count 
      from sessions 
      group by 1 
     ) union all (
      select date_trunc('minute', ts_end) as minute, - count(*) as count 
      from sessions 
      group by 1 
     ) 
    ) s1 
    group by minute 
) s2 
order by minute; 

爲了便於比較,這裏有一個小時的數據的時序結果:

  1. 原始查詢時間:81301.345毫秒
  2. 總和,在查詢時間:36242.342毫秒

回答

2

通過計算每分鐘的啓動和停止次數,然後計算累計和,您可以更快地做到這一點。結果是這樣的:

select minute, sum(cnt) over (order by minute) 
from ((select date_trunc('minute', ts_start) as minute, count(*) as cnt 
     from sessions 
     group by 1 
    ) union all 
     (select date_trunc('minute', ts_end), - count(*) 
     from sessions 
     group by 1 
    ) 
    ) s 
group by minute 
order by minute; 
+0

這幾乎得到它。因爲窗口函數不是聚合函數,所以Redshift不會讓我在外部作用域中分組。我將嘗試總結開始和結束時的總和,然後按照常規總和在外部範圍逐分鐘進行總結。 – systemjack

+0

我通過在計算滾動總和之前捕獲每分鐘的差異來使其工作。我得到的數字看起來是正確的。太棒了!非常感謝! – systemjack

+0

仍不完全正確。這種方法的缺陷是當用戶的會話結束並且新的會話在同一分鐘內開始時,這在我的真實數據集中經常是這樣。這會導致少量的計數不足。 – systemjack

相關問題