2012-03-07 59 views
1

我有一個包含用戶會話的表格,即用戶在我的應用程序中登錄的時間段。每個會話都有一個開始和結束時間戳。查詢從會話表中獲取高峯時間

我可以通過一個查詢確定當天每小時有多少用戶當時在線(即多少次會話有startTime <= hour AND endTime > hour)? 我想顯示過去2個月的平均值,但如果這是不可能的,我可以用1天的查詢進行管理並計算腳本中的平均值。

樣品結果:

Hour Online 
00:00 10 
01:00 12 
02:00 10 
.... 
16:00 100 
17:00 120 
.... 

(小時也可以是簡單的整數,沒有多大意義)

的數據庫爲MySQL 5

+1

小時在線用戶和每月平均在同一查詢中?這是不會飛:) – 2012-03-07 11:21:43

+0

你可以請給出一個示例結果集給你需要的所有列。 – Tobsey 2012-03-07 11:38:14

+0

@Tobsey新增。正如你可以看到它沒什麼特別的(結果,查詢可能是) – 2012-03-07 12:42:07

回答

1

我等着別人來步入,因爲我不熟悉mysql,我相信必須有更好的解決方案。

這裏的主要問題是一天中構建小時表的方法。在mysql中沒有遞歸選擇能力迫使我通過聯合來創建表。如果我們可以接受在當天沒有人登錄的情況下缺少日期,則日期更加容易。如果不是,可以使用與小時類似的技巧來延長日期,例如七天。 交叉連接將生成一個日期表,每個日期都有24小時。現在我們需要計算在這個時間點處於活動狀態的會話。爲此,我們需要將startTime截斷爲小時邊界,並將交叉連接組合時間放在截斷的startTime和endTime(不需要截斷)內。我們的數據終於來了。

要獲得前兩個月的平均值,只需在另一個分組小時中計算平均值並計算avg(Users)即可。如果您確實必須具有單個查詢才能返回兩個數據集,則可以將此查詢與平均查詢結合起來,其中平均查詢將返回null作爲日期。

其他免責聲明:如前所述,我不知道MySql。我嘗試使用在線手冊編寫日期和時間轉換功能。可能失敗了,但我相信你會糾正我的。我也不確定保留關鍵字。

select days.date, 
hour, 
count (s.startTime) Users 
from 
(
    (
     select 0 hour 
     union 
     select 1 hour 
     union 
     select 2 hour 
     union 
     select 3 hour 
     union 
     select 4 hour 
     union 
     select 5 hour 
     union 
     select 6 hour 
     union 
     select 7 hour 
     union 
     select 8 hour 
     union 
     select 9 hour 
     union 
     select 10 hour 
     union 
     select 11 hour 
     union 
     select 12 hour 
     union 
     select 13 hour 
     union 
     select 14 hour 
     union 
     select 15 hour 
     union 
     select 16 hour 
     union 
     select 17 hour 
     union 
     select 18 hour 
     union 
     select 19 hour 
     union 
     select 20 hour 
     union 
     select 21 hour 
     union 
     select 22 hour 
     union 
     select 23 hour 
    ) hours 
    cross join 
    (
    -- We need date portion only 
     select distinct date(startTime) date from s 
     union select distinct date(endTime) from s 
    ) days 
) 
left join s 
-- date+hour, hopefully 
    on date_add(date, interval hour HOUR) 
    -- startTime is truncated to hour, hopefully 
     between date_sub(s.startTime interval minutes(s.startTime) MINUTE) 
     and s.endTime 
-- last two months 
where days.date between date_sub (now() interval 2 MONTH) and now() 
group by days.date, hour 
order by 1, 2 
+1

沒有工作,但我設法建立一些東西(見我的答案) – 2012-03-07 16:13:47

0

我不能設法得到尼古拉的查詢工作,但使用一些從它的技術來創建此查詢,從而可以獲得平均每小時爲整個時期,這是不夠好。

SELECT hour, AVG(dayHourCount) FROM 

(
SELECT hour, day, dayHour, COUNT(*) AS dayHourCount FROM 
(
SELECT hour, day, day + INTERVAL hour HOUR AS dayHour FROM 
    (
     select 0 AS hour 
     union 
     select 1 AS hour 
     union 
     select 2 AS hour 
     union 
     select 3 AS hour 
     union 
     select 4 AS hour 
     union 
     select 5 AS hour 
     union 
     select 6 AS hour 
     union 
     select 7 AS hour 
     union 
     select 8 AS hour 
     union 
     select 9 AS hour 
     union 
     select 10 AS hour 
     union 
     select 11 AS hour 
     union 
     select 12 AS hour 
     union 
     select 13 AS hour 
     union 
     select 14 AS hour 
     union 
     select 15 AS hour 
     union 
     select 16 AS hour 
     union 
     select 17 AS hour 
     union 
     select 18 AS hour 
     union 
     select 19 AS hour 
     union 
     select 20 AS hour 
     union 
     select 21 AS hour 
     union 
     select 22 AS hour 
     union 
     select 23 AS hour 
    ) AS hours 

INNER JOIN (SELECT DISTINCT DATE(start) AS day FROM PlayerSession ds WHERE ds.start > NOW() - INTERVAL 1 MONTH) AS days 
) AS dayHours 

LEFT JOIN PlayerSession s ON (s.start < dayHour AND s.lastActivity > dayHour) 
LEFT JOIN Player p ON (s.player_id = p.id) 

GROUP BY dayHour 

) AS perDayHour 

GROUP BY hour