2013-03-25 43 views
0

我有一個表格式如下:用戶「分鐘工作」。如何使這個查詢?

id, user, action, date 
1, user1, a1, 2013-03-20 10:00:01 
2, user2, a1, 2013-03-20 10:00:03 
3, user2, a1, 2013-03-20 10:00:12 
4, user3, a1, 2013-03-20 10:00:20 
5, user2, a1, 2013-03-20 10:00:24 
.... 
... 

,並繼續在所有分鐘和小時(全天候)與30型動物的用戶...

現在我需要知道「分鐘的工作」 .. 。例如:

  1. 如果我只有一個用戶全天,我有24小時* 60分鐘= 1440分鐘 今天工作。
  2. 如果是全天(24小時)2級的用戶將是:2880分鐘 工作...

但是......用戶不要整天工作(當然..)我怎麼能做出這種查詢?

解答一些問題:

  • 我需要(從所有 用戶分鐘的總和)得到所有用戶的分鐘的工作
  • 我asume「註銷」的用戶,如果他們不在5分鐘內做任何動作。
  • 我可以使用一些PHP代碼來完成這項工作。
+4

[你有什麼嘗試?](http://www.whathaveyoutried.com/)請參見[ask advice](http://stackoverflow.com/questions/ask-advice)。 – 2013-03-25 02:23:39

+0

預期產量是多少?你只是想總結給定用戶至少工作一次的所有分鐘嗎? – Patashu 2013-03-25 02:29:19

+0

所以你有一個表記錄他們所有的行爲?你如何定義用戶何時停止工作?如果他們還沒有在30分鐘內做出行動?或者是在任何一天的第一次和最後一次行動之間的時間跨度? – mpen 2013-03-25 02:29:42

回答

1

此查詢的確如此。

SELECT user, CAST(date AS DATE) day, (SUM(worked_seconds)/60) minutes 
FROM (
     SELECT w1.user 
     ,   w1.date 
     ,   UNIX_TIMESTAMP(
        LEAST(
        MIN(IFNULL(w2.date, w1.date + INTERVAL 5 MINUTE)), 
        CAST(w1.date AS DATE) + INTERVAL 1 DAY 
       ) 
       ) 
       - UNIX_TIMESTAMP(w1.date) worked_seconds 
     FROM  work w1 
     LEFT JOIN work w2 
     ON  w1.user = w2.user 
     AND  w1.date < w2.date 
     AND  w1.date + INTERVAL 5 MINUTE > w2.date 
     AND  CAST(w1.date AS DATE) = CAST(w2.date AS DATE) 
     GROUP BY w1.user, w1.date 
) work 
GROUP BY user, day 

在5分鐘間隔內的查詢對每個工作行具有相同的用戶的所有後來的工作行(ON w1.user = w2.user)(AND w1.date < w2.data AND w1.date + INTERVAL 5 MINUTE> w2.date),前提是工作發生在同一天(CAST(w1.date AS DATE)= CAST(w2.date AS DATE)

根據定義,不會有後續行對於特定日期的最後一行,因爲我們使用的是LEFT JOIN,所以會產生一個NULL值。我們假設對於最後一行,根據註銷規則完成5分鐘的工作(IFNULL(w2.date ,w1.date + INTERVAL 5 MINUTE)

對於每個(日期,用戶)行可能找到多個後面的行,在這種情況下,我們希望找到最早的行,以便計算兩個日期之間的差異。這是使用MIN函數完成的。

現在,由於最後一行+ 5分鐘的時間間隔可能會超出當天的結束時間,因此我們使用LEAST來防止這種情況。

UNIX_TIMESTAMP在那裏可以將日期時間轉換爲秒,所以我們可以輕鬆地減去它們並獲得工作秒數。

在外層查詢中,最後我們將每個用戶的工作總和除以60,以便從秒到分鐘。