web-dev-qa-db-ja.com

1つの行の「TIME_IN」データと次の行の「TIME_OUT」データに基づいて、1日あたりの合計時間を計算します

オフィスで1日あたりに費やした実際の時間を計算する必要があります。オンラインでいくつかの例を見てきましたが、すべて同じ行にTIME_INとTIME_OUTがあります。私のアプリケーションは、「Enter」または「Exit」がトラッキングデバイスによって記録されるたびに、エントリを新しい行に入れます。次のクエリを使用して、「通常」の1日あたりの全体的な時間を計算できます。

タイムログを使用します。

mysql> SELECT TIMEDIFF(MAX(date_time), MIN(date_time)) FROM timelog WHERE day_of_month="11";

+------------------------------------------+
| TIMEDIFF(MAX(date_time), MIN(date_time)) |
+------------------------------------------+
| 09:06:00                                 |
+------------------------------------------+
1 row in set (0.00 sec)

11日のすべてのIN/OUTのデータ:

mysql> SELECT status,date_time FROM timelog WHERE day_of_month="11";

+--------+---------------------+
| status | date_time           |
+--------+---------------------+
| IN     | 2017-04-11 08:39:00 |
| OUT    | 2017-04-11 09:42:00 |
| IN     | 2017-04-11 10:03:00 |
| OUT    | 2017-04-11 10:38:00 |
| IN     | 2017-04-11 10:43:00 |
| OUT    | 2017-04-11 12:09:00 |
| IN     | 2017-04-11 13:20:00 |
| OUT    | 2017-04-11 13:24:00 |
| IN     | 2017-04-11 13:26:00 |
| OUT    | 2017-04-11 14:06:00 |
| IN     | 2017-04-11 14:13:00 |
| OUT    | 2017-04-11 17:45:00 |
+--------+---------------------+

テーブル:タイムログ

Description: mysql> desc timelog;
+--------------+----------+------+-----+---------+-------+
| Field        | Type     | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+-------+
| status       | char(3)  | NO   |     | NULL    |       |
| date_time    | datetime | YES  |     | NULL    |       |
| day_of_week  | char(9)  | YES  |     | NULL    |       |
| month        | char(10) | YES  |     | NULL    |       |
| day_of_month | int(2)   | YES  |     | NULL    |       |
| year         | int(4)   | NO   |     | NULL    |       |
| hour         | int(2)   | YES  |     | NULL    |       |
| minute       | int(2)   | YES  |     | NULL    |       |
| time_of_day  | time     | YES  |     | NULL    |       |
| SSID         | char(15) | YES  |     | NULL    |       |
+--------------+----------+------+-----+---------+-------+

11日のすべてのデータ:

mysql> SELECT * FROM timelog WHERE day_of_month="11";
+--------+---------------------+-------------+-------+--------------+------+------+--------+-------------+----------------+
| status | date_time           | day_of_week | month | day_of_month | year | hour | minute | time_of_day | SSID           |
+--------+---------------------+-------------+-------+--------------+------+------+--------+-------------+----------------+
 |IN     | 2017-04-11 08:39:00 | Tuesday     | April |           11 | 2017 |    8 |     39 | 08:39:00    | CGP Financial
 |OUT    | 2017-04-11 09:42:00 | Tuesday     | April |           11 | 2017 |    9 |     42 | 09:42:00    | CGP Financial
 |IN     | 2017-04-11 10:03:00 | Tuesday     | April |           11 | 2017 |   10 |      3 | 10:03:00    | CGP Financial
 |OUT    | 2017-04-11 10:38:00 | Tuesday     | April |           11 | 2017 |   10 |     38 | 10:38:00    | CGP Financial
 |IN     | 2017-04-11 10:43:00 | Tuesday     | April |           11 | 2017 |   10 |     43 | 10:43:00    | CGP Financial
 |OUT    | 2017-04-11 12:09:00 | Tuesday     | April |           11 | 2017 |   12 |      9 | 12:09:00    | CGP Financial
 |IN     | 2017-04-11 13:20:00 | Tuesday     | April |           11 | 2017 |   13 |     20 | 13:20:00    | CGP Financial
 |OUT    | 2017-04-11 13:24:00 | Tuesday     | April |           11 | 2017 |   13 |     24 | 13:24:00    | CGP Financial
 |IN     | 2017-04-11 13:26:00 | Tuesday     | April |           11 | 2017 |   13 |     26 | 13:26:00    | CGP Financial
 |OUT    | 2017-04-11 14:06:00 | Tuesday     | April |           11 | 2017 |   14 |      6 | 14:06:00    | CGP Financial
 |IN     | 2017-04-11 14:13:00 | Tuesday     | April |           11 | 2017 |   14 |     13 | 14:13:00    | CGP Financial
 |OUT    | 2017-04-11 17:45:00 | Tuesday     | April |           11 | 2017 |   17 |     45 | 17:45:00    | CGP Financial
+--------+---------------------+-------------+-------+--------------+------+------+--------+-------------+----------------+

今私の質問のために... :-)

各INとOUTの間の時間に基づいて、オフィスで費やした実際の時間を最もよく計算するにはどうすればよいですか? 「09:42」から「10:03」までの時間を非稼働時間としてマークし、「10:03」から「10:38」までの時間を稼働時間としてマークできるようにしたい、など。私はその日の最初を除いてすべての「IN」時間を否定して追加しようとしましたが、それはうまくいかなかったようです。

誰かが、毎日のIN/OUTタイムスタンプをステップ実行し、オフィスで費やされた「実際の」時間を計算するSQLステートメント(私は決して初心者でもありません)の作成を手伝ってくれませんか?

私は月を求めているので、火星も求めるかもしれません。私はオンコールの対象となるため、真夜中過ぎによく働くこと、または今朝の場合のように01:00から02:45までオフィスに電話されることが珍しくありません。 「過去の真夜中」と「早い段階で帰ってきて、家に帰って、08:00に戻ってきた」を計算に入れることもできます。

さらに情報が必要な場合、または私が投稿した内容の説明が必要な場合は、お知らせください。あなたの助けは大歓迎です。

ブライアン

3
Bryan Moorehead

最も重要なことは、時間と時間を一致させることです。以下のクエリは、これを実現する1つの方法を示しています。

以下のアプローチは、個人が「時間を計った」時間に働いた時間を特定します...時間をそれが発生した日に帰する試みはありません(このニーズに対処するこのサイトには他の質問があります)。

 select in_time,
         ifnull(out_time,now()) as out_time,
         unix_timestamp(ifnull(out_time,now())) - unix_timestamp(in_time) as seconds_in
    from (select date_time in_time,
                 (select min(date_time)
                    from timelog
                   where status='OUT'
                     and date_time > t.date_time) as out_time
            from timelog t
           where status='IN'
         ) as in_out;
+---------------------+---------------------+------------+
| in_time             | out_time            | seconds_in |
+---------------------+---------------------+------------+
| 2017-04-11 08:39:00 | 2017-04-11 09:42:00 |       3780 |
| 2017-04-11 10:03:00 | 2017-04-11 10:38:00 |       2100 |
| 2017-04-11 10:43:00 | 2017-04-11 12:09:00 |       5160 |
| 2017-04-11 13:20:00 | 2017-04-11 13:24:00 |        240 |
| 2017-04-11 13:26:00 | 2017-04-11 14:06:00 |       2400 |
| 2017-04-11 14:13:00 | 2017-04-11 17:45:00 |      12720 |
+---------------------+---------------------+------------+
6 rows in set (0.00 sec)

次に、毎日の秒数を合計します...

select date(in_time),
       sum(seconds_in)
 from (select in_time,
              ifnull(out_time,now()) as out_time,
              unix_timestamp(ifnull(out_time,now())) - unix_timestamp(in_time) as seconds_in
         from (select date_time in_time,
                      (select min(date_time)
                         from timelog
                        where status='OUT'
                          and date_time > t.date_time) as out_time
                 from timelog t
                where status='IN'
              ) as in_out
      ) as q1
group by date(in_time);
+---------------+-----------------+
| date(in_time) | sum(seconds_in) |
+---------------+-----------------+
| 2017-04-11    |           26400 |
+---------------+-----------------+
1 row in set (0.01 sec)
1
RMathis

私も同じ問題を抱えています。これまではさまざまなツールを使用して、従業員を並べ替え、次に日時を降順に並べ替えることで解決しました。この時点で、クエリ(A)に追加するインデックス列を0から作成しました。その後、重複するクエリ(B)を作成し、1で始まるインデックス列を作成しました。作成したインデックス列を使用してクエリA&Bに結合し、それらのOut Timesに同じ行の前のレコードが含まれるようにしました。次に、レコードにoutステータスがあるかどうかを示すIfステートメントを実行し、タイムスタンプと前のレコードのタイムスタンプとの差を取ります。これは複雑な問題です。誰かがドアを開けたままにしたりすると、指紋をスキャンせずに建物を離れることができるため(そうです)、2つのINレコードを背中合わせにして、Vice Versaにoutレコードを置くことができます。これらの状況も考慮する必要がありますが、すべての方法がうまく機能し、Power BIを使用してインデックスを作成できます。私は誰かがMYSQL側でこの問題を解決できることを望んでいました。これがPower BIから提供されたものです。

Power BI Example of Finished Product

0
Kevin Martin