0

この形式のテーブルが 1 つあります。

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 人の異なるユーザーと何分も何時間も (24 時間 365 日) 続けます...

今、私は「分の仕事」を知る必要があります...例:

  1. 1 日中 1 人のユーザーしかいない場合、今日の作業時間は 24 時間 * 60 分 = 1440 分です。
  2. 1 日 (24 時間) で 2 人のユーザーの場合: 2880 分作業...

しかし... ユーザーは一日中働いていません (もちろん..) どうすればこのクエリを作成できますか?

いくつかの質問への回答:

  • すべてのユーザーによる分数の作業を取得する必要があります (すべてのユーザーからの分数の合計)
  • ユーザーが 5 分以内に何もしない場合、ユーザーの「ログアウト」を想定しています。
  • PHPコードを使用して、これを機能させることができます。
4

1 に答える 1

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 分間隔 (AND w1.date < w2.data AND w1.date + INTERVAL 5 MINUTE > w2.作業が同じ日に行われた場合 (CAST(w1.date AS DATE) = CAST(w2.date AS DATE))。

定義上、特定の日の最後の行には後の行はありません。LEFT JOIN を使用しているため、これは NULL 値になります。その最後の行では、ログアウト ルール (IFNULL(w2.date, w1.date + INTERVAL 5 MINUTE) に従って 5 分間の作業が行われたと仮定します)

(日付、ユーザー) 行ごとに複数の後の行が見つかる可能性があります。その場合、2 つの日付の差を計算できるように、最も古い行を見つけたいと考えています。これは MIN 関数を使用して行われます。

ここで、最後の行 + 5 分の間隔が 1 日の終わりを超える可能性があるため、LEAST を使用してそれを防ぎます。

UNIX_TIMESTAMP は日時を秒に変換するためにあるので、それらを簡単に差し引いて作業秒数を取得できます。

外側のクエリでは、最後にユーザーごとの作業を合計し、60 で割って秒から分にします。

于 2013-03-25T19:18:24.657 に答える