2010-03-18 63 views
3

我正在寫一個SQLite數據庫的基於統計的應用程序。有一個表記錄用戶何時登錄和註銷(SessionStart,SessionEnd日期時間)。SQL查詢:如果給定兩個DateTime時間戳,如何確定「在N小時內看到」?

我在找的是一個查詢,它可以顯示用戶已有已登錄的時間,以線形圖的方式進行登錄 - 所以在12:00到凌晨1:00之間,有60個用戶登錄(在任何時間點),凌晨1點到凌晨2點之間有54個用戶登錄,等等......

而且我希望能夠運行這個SUM,這就是爲什麼我無法將這些記錄帶入.NET,並以這種方式遍歷它們。

我已經想出了一個相當原始的方法,每天每個小時都有一個子查詢,但是這種方法已被證明是緩慢和緩慢的。我需要能夠計算這個的一對夫婦十萬條記錄在一瞬間..

SELECT 
     case 
     when (strftime('%s',datetime(date(sessionstart), '+0 hours')) > strftime('%s',sessionstart) 
     AND strftime('%s',datetime(date(sessionstart), '+0 hours')) < strftime('%s',sessionend)) 
     OR (strftime('%s',datetime(date(sessionstart), '+1 hours')) > strftime('%s',sessionstart) 
     AND strftime('%s',datetime(date(sessionstart), '+1 hours')) < strftime('%s',sessionend)) 
     OR (strftime('%s',datetime(date(sessionstart), '+0 hours')) < strftime('%s',sessionstart) 
     AND strftime('%s',datetime(date(sessionstart), '+1 hours')) > strftime('%s',sessionend)) 
     then 1 else 0 end as hour_zero, 
... hour_one, 
... hour_two, 
........ hour_twentythree 
FROM UserSession 

我想知道什麼更好的方式來確定兩個DateTime是否已經看到durring特定小時(最好的情況下,如果它在多個天內登錄,但是沒有必要,它多少次超過一小時)?

我唯一的想法是有一個特定於此的「小時」表,並且只是計算用戶在運行時看到的小時數,但我覺得這比以前的SQL更像黑客攻擊。

任何幫助將不勝感激!

+0

你不關心DATE部分嗎?您是否需要爲整個歷史記錄,某個日期範圍或每一天的每個小時分別彙總? – van 2010-03-18 20:05:43

+0

切割日期部分的唯一問題是有些用戶可能會登錄超過一天,所以最好的情況是能夠在25小時的會話期間考慮額外的小時。 我會聚合每個小時爲一個特定的用戶,或另一個標識符在桌子上。儘管如此,這可能包括數十萬次會議。 – efess 2010-03-19 13:26:03

回答

1

也許你可能有另一張表,記錄登出時間時,填充記錄以確定用戶登錄時的小時數?

例如

create table hourlyUseLog (
    userID text not null, 
    date float, // julian Day 
    hour0 integer default 0, 
    hour1 integer default 0, 

etc... 

    hour23 integer default 0, 
); 

如果你有這樣的結構,你可以做誰是在任何給定的時間/日期記錄(或很多用戶是如何登錄)的非常快的查詢。

SQLite還支持位字段和位數學運算,因此您還可以用單個整數表示一天中的所有小時數,並根據用戶活動的小時數來翻轉位。這將允許您使用位掩碼進行更快的查詢,並提供一種將小時轉換爲朱利安日(僅限時間部分)表示和/或使用計數例程來計算系統中花費的時間的機制。另外,如果您需要實時活動報告,並且您的系統允許您集中表示誰已登錄,則可以啓動每小時一次的批處理過程,以更新hourlyUseLog記錄。

+0

我認爲這是最好的方法。馬丁的答案比我的要乾淨得多,但是,它和我一樣執行和/或操作,速度也一樣慢。 我想我會走這條路線,我認爲是最好的解決方案的小時日誌或彙總表。 謝謝大家 – efess 2010-03-19 12:43:10

1

我會用你的「黑客」的想法,但我不認爲它是一個黑客,真的 - 一小時後,價值將永遠不會改變,所以爲什麼不計算一次,並與它?彙總表對此完全有效,無論您一直跟蹤多少用戶,都會產生一致的查詢時間。

您可以每小時計算一次,或者您可以在登錄/註銷事件中增加每小時的計數器數量,並避免計劃任務。

2

在Sybase(T-SQL方言)上玩了一下,並提出了這個查詢。

SELECT 
    StartHour AS Hour, COUNT(*) AS SessionCount 
FROM 
    (SELECT 
     CONVERT(DATETIME, '2001-01-01 ' + Hour + ':00:00') as StartHour, 
     DATEADD(HH, 1, CONVERT(DATETIME, '2001-01-01 ' + Hour + ':00:00')) as EndHour 
    FROM 
     (SELECT '00' AS Hour UNION ALL SELECT '01' AS Hour UNION ALL 
     SELECT '02' AS Hour UNION ALL SELECT '03' AS Hour UNION ALL 
     SELECT '04' AS Hour UNION ALL SELECT '05' AS Hour UNION ALL 
     SELECT '06' AS Hour UNION ALL SELECT '07' AS Hour UNION ALL 
     SELECT '08' AS Hour UNION ALL SELECT '09' AS Hour UNION ALL 
     SELECT '10' AS Hour UNION ALL SELECT '11' AS Hour UNION ALL 
     SELECT '12' AS Hour UNION ALL SELECT '13' AS Hour UNION ALL 
     SELECT '14' AS Hour UNION ALL SELECT '15' AS Hour UNION ALL 
     SELECT '16' AS Hour UNION ALL SELECT '17' AS Hour UNION ALL 
     SELECT '18' AS Hour UNION ALL SELECT '19' AS Hour UNION ALL 
     SELECT '20' AS Hour UNION ALL SELECT '21' AS Hour UNION ALL 
     SELECT '22' AS Hour UNION ALL SELECT '23' AS Hour) AS Hours 
    ) AS T1, 
    UserSession AS T2 
WHERE 
    -- Logged on during, logged off during 
    (T2.SessionStart >= T1.StartHour AND T2.SessionEnd < T1.EndHour) 
    -- Logged on before, logged off during 
    OR (T2.SessionStart < T1.StartHour AND T2.SessionEnd >= StartHour AND T2.SessionEnd < T1.EndHour) 
    -- Logged on during, logged off after 
    OR (T2.SessionStart >= T1.StartHour AND T2.SessionStart < T1.EndHour AND T2.SessionEnd >= T1.EndHour) 
    -- Logged on before, logged off after 
    OR (T2.SessionStart < T1.StartHour AND T2.SessionEnd >= T1.EndHour) 
GROUP BY 
    T1.StartHour 
ORDER BY 
    T1.StartHour 

需要的輸入是以YYYY-MM-DD形式聚合的日子。請注意,它不會在計數爲零的小時內返回任何結果。