2013-04-30 104 views
0

我有一個用戶訪問日誌表的應用程序。以下是一些示例數據:並行用戶儀表板

userid |   login   | duration (seconds) 
-------------------------------------------------------- 
1   | 2013-04-30 09:24:07.127 | 21456  
2   | 2013-04-29 09:22:05.023 | 26477  
1   | 2013-04-30 10:24:07.787 | 86543  
2   | 2013-04-30 12:55:55.846 | 32237  
1   | 2013-04-30 08:24:12.347 | 92231  

我的目標是從這些數據中獲得一些指標。我需要捕獲過去一週內最小,最大和平均併發登錄用戶數。除非有人有更好的主意,否則我相信要獲得併發連接的有意義的平均值,我需要選擇一個時間間隔。如果我在那裏錯了,請糾正我。如果是這樣,我認爲我不應該有這方面的麻煩。它的最小和最大的給我的問題。我試圖在SQL中這樣做,但無濟於事。問題在於如何衡量連接之間的重疊。我應該拉出來,並在Python中做到這一點。我會有100,000多行,所以它可能會有點麻煩,但我只需要每天生成一次報告,所以效率並不是我最關心的問題。

對不起,我沒有任何示例代碼,我真的不知道如何從這裏開始。謝謝您的幫助。

+0

如果你想做一段時間然後[this](http://stackoverflow.com/questions/12428873/avoiding-gaps-in-datetime-intervals-with-cte-and-start- and-end-datetimes/12504291#12504291)可能會有所幫助。儘管您可以總結所有時間的數據,但是它在數據庫超過幾年之後真的有意義嗎? – HABO 2013-04-30 14:49:53

+0

我只需要捕獲一週或更新的數據。 – Hoopdady 2013-04-30 15:11:42

+0

如果您正在嘗試評估系統上的負載,我無法想象這些用戶在登錄後仍處於活動狀態。 – JeffO 2013-04-30 15:45:54

回答

0

這是應該幫助的。例如,您可能必須努力弄清楚如何處理周邊界。

這個想法是將數據分解爲登錄和註銷。登錄發生在登錄後的登錄+秒秒以便輕鬆計算。每個登錄名的值爲+1(併發用戶數加1)。每個註銷的值都是-1

該版本的查詢使用相關的子查詢來計算併發用戶的數量和到下一個事件的時間。在SQL Server 2012中,這些可以用累加和來代替(sum() over (partition . . order by)lead()

最後一步是計算平均值,這需要考慮持續時間的準確性。它會懷念在開始階段並沒有結束登錄爲此,你可能需要用的0到事件的值添加虛假記載CTE:

with d as (
     select 1 as userid, CAST('2013-04-30 09:24:07.127' as datetime) as logint, 21456 as secs union all 
     select 2, CAST('2013-04-29 09:22:05.023' as datetime), 26477 union all 
     select 1 , CAST('2013-04-30 10:24:07.787' as datetime), 86543 union all 
     select 2, CAST('2013-04-30 12:55:55.846' as datetime), 32237 union all 
     select 1, CAST('2013-04-30 08:24:12.347' as datetime), 92231 
    ), 
    events as (
     select logint as thetime, 1 as loginp 
     from d 
     union all 
     select DATEADD(second, secs, logint), -1 
     from d 
    ), 
    t as (
     select e.*, 
      (select SUM(loginp) from events e2 where e2.thetime <= e.thetime) as concurrents, 
      (select top 1 thetime from events e2 where e2.thetime > e.thetime order by e2.thetime desc) as nexttime, 
      DATEDIFF(second, thetime, (select top 1 thetime from events e2 where e2.thetime > e.thetime order by e2.thetime desc)) as dur 
     from events e 
    ) 
select SUM(concurrents*1.0*dur)/SUM(dur) as avg_concurrents, 
     MIN(concurrents), MAX(concurrents) 
from t 

這是假定沒有重複的時間 - 你沒有辦法區分問題中的重複,如果你有一個id,很容易就可以把它弄清楚下一步會發生什麼,比使用時間。

+0

所以對我來說有點難以遵循一些邏輯,但是我很困惑你爲什麼要用'd'(選擇......),然後你選擇樣本表中的每一行。知道表中的內容是什麼,所以它很難將這些值插入到查詢中,但是,我的表格也有100,000多行,我不想選擇並聯合所有這些值。你提出的建議是什麼? – Hoopdady 2013-04-30 15:22:07

+0

@Hoopdady - 調試或理解這種類型的操作的一種方法是將最後一個'select'替換爲顯示中間結果的'select'。'select * from d'將顯示您的樣本數據。 'select * from events'顯示它變成了登錄表(+1)和退出表(-1)。 'select * from t'顯示_的第一部分,然後出現一個奇蹟。 – HABO 2013-04-30 19:39:40