web-dev-qa-db-fra.com

Calculez les heures totales par jour en fonction des données «time_in» dans une ligne et des données «time_out» sur la ligne suivante

Je dois calculer le temps réel passé au bureau par jour. J'ai vu plusieurs exemples en ligne, mais ils ont tous le temps_in et l'heure dans la même rangée. Mon application met les entrées dans une nouvelle ligne chaque fois qu'une "entrée" ou "sortie" est enregistrée par le périphérique de suivi. Je suis capable de calculer le temps total par jour pour une journée "normale" avec la requête suivante:

utiliser timelog;

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)

Les données pour tous in/out le 11:

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 |
+--------+---------------------+

Table: Timelog

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    |       |
+--------------+----------+------+-----+---------+-------+

Toutes les données pour le 11ème:

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
+--------+---------------------+-------------+-------+--------------+------+------+--------+-------------+----------------+

Maintenant, pour ma (s) question (s) ... :-)

Comment calculer le mieux le temps réel passé dans le bureau en fonction du temps entre chacun d'eux-mêmes? J'aimerais être capable de marquer le temps entre dire "09:42" et "10:03" comme le temps non travaillé et le temps entre "10:03" et "10:38" comme travaillé, et ainsi de suite . J'ai essayé de nier tous les temps "dans", à l'exception du premier jour et d'ajout, mais cela ne semblait pas fonctionner.

Quelqu'un peut-il m'aider à créer une déclaration SQL (je ne suis nullement qu'un novice) qui traversera chaque jour des horodatages de chaque jour et de calculer le temps "réel" passé au bureau?

Depuis que je demande la lune, je pourrais aussi bien demander que Mars aussi. Comme je suis soumis à l'appel, il n'est pas rare que moi de travailler bien après minuit, ou comme dans le cas de ce matin, soyez appelé au bureau de 01h00 à 02h45, alors je voudrais donc Être capable de facteur "après minuit" et "est arrivé tôt, rentré à la maison, est revenu à 08h00" dans l'équation aussi.

Si vous avez besoin de plus d'informations, ou des éclaircissements sur tout ce que j'ai posté, merci de me le faire savoir. Votre aide est très appréciée.

Bryan

3
Bryan Moorehead

Il semble que la chose la plus importante correspond à l'heure correspondante avec le temps dedans. La requête ci-dessous montre une manière que cela puisse être accompli.

L'approche ci-dessous attribue le temps a travaillé lorsque l'individu "Holided" in ... Il n'ya aucune tentative d'attribuer l'heure à la journée dans laquelle elle s'est produite (il existe d'autres questions sur ce site qui répondent à ce besoin).

 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)

Maintenant, résumer les secondes pour chaque jour ...

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

Moi aussi j'ai le même problème. Dans le passé avec des outils différents, je l'ai résolu en triant les employés, puis triez sur la date de descente. À ce stade, j'ai créé une colonne d'index à partir de 0 à ajouter à ma requête (A). J'ai ensuite fait une requête en double (B) après cela et crée une colonne d'index commençant par 1. J'ai rejoint la requête A & B à l'aide des colonnes d'index que j'ai apportées afin que leurs heures de sortie avaient des enregistrements précédents de la même rangée. J'ai ensuite fait une déclaration IF disant si l'enregistrement dispose d'un statut de sortie, prenez la différence entre l'horodatage et l'horodatage précédent. C'est un problème complexe, car parfois des gens peuvent quitter le bâtiment sans scanner leurs empreintes digitales (oui, nous avons ces) si quelqu'un tient la porte ouverte ou quelque chose, vous pouvez donc avoir deux enregistrements dans le dos et inversement avec les enregistrements de sortie. Vous devez également prendre votre compte pour ces situations, mais dans l'ensemble de cette méthode fonctionne assez bien et que vous pouvez utiliser la puissance BI pour l'indexation. J'espérais juste que quelqu'un puisse résoudre ce problème sur le côté mysql. Voici quel pouvoir bi m'a donné.

Power BI Example of Finished Product

0
Kevin Martin