来自mysql数据库的每周工作报告

时间:2015-11-10 15:32:43

标签: mysql sql

我正在尝试从我的mysql数据库获取员工的每周工作报告。

我有四张桌子:

stdjobs (ID, NR, Name, Gruppe)
user (ID, vname, nname, NR)
wtime (ID, usr, job, tin, tout)
Groups (idGroups, NR, Name)

stdjobs中是一些标准作业代码的全名。在user我有一些关于我的用户的更多详细信息。此查询不使用Groups

wtime是主表,员工进入工作时间(通过简单的c-prog和条形码扫描仪)。

select * from wtime order by id desc limit 5;

返回类似这样的内容:

ID    usr    job      tin                  tout
4843  M0005  A001942  2015-11-10 15:18:47  NULL
4842  M0006  A001843  2015-11-10 14:47:23  NULL
4841  M0007  A001814  2015-11-10 13:33:37  NULL
4840  M0007  .000002  2015-11-10 13:27:10  2015-11-10 13:33:37
4839  M0006  A001814  2015-11-10 13:25:19  2015-11-10 14:47:23

tout - 带有NULL的字段表示实际工作的作业。

我希望每个员工每周都能获得一份报告,其中包括白天和整个星期的总和。看起来应该是这样的:

Report for Gxxxxxxx Zxxxxxxxxxx

Date             Job      In        Out       Time
Mon, 15.01.2015  A001814  06:58:35  08:45:26  01:46:51
Mon, 15.01.2015  A001925  08:45:26  09:45:26  01:00:00
Mon, 15.01.2015  NULL     NULL      NULL      02:46:51
Thu, 16.01.2015  A001814  06:00:00  08:00:00  02:00:00
Thu, 16.01.2015  A001925  08:00:00  10:00:00  02:00:00
Thu, 16.01.2015  NULL     NULL      NULL      04:00:00
NULL             NULL     NULL      NULL      06:46:51

现在我有以下查询:

SET lc_time_names = 'de_AT';
SELECT 
    (SELECT 
            CONCAT(vname, ' ', nname)
        FROM
            zeiterf.user
        WHERE
            nr = zeiterf.wtime.usr
        LIMIT 1) AS 'Name',
    DATE_FORMAT(tin, '%a %e.%c.%Y') AS 'Datum',
    IF((SELECT 
                name
            FROM
                zeiterf.stdjobs
            WHERE
                nr = zeiterf.wtime.job
            LIMIT 1) != '',
        (SELECT 
                name
            FROM
                zeiterf.stdjobs
            WHERE
                nr = zeiterf.wtime.job
            LIMIT 1),
        job) AS 'Auftrag',
    TIME(tin) AS 'Ein',
    IF(job != '...ENDE', TIME(tout), NULL) AS 'Aus',
    (IF(job != '...ENDE',
        SEC_TO_TIME(UNIX_TIMESTAMP(tout) - UNIX_TIMESTAMP(tin)),
        NULL)) AS 'Zeit'
FROM
    zeiterf.wtime
WHERE
    usr = 'M0006' AND job != '...ENDE'
        AND DATE(tin) > (DATE_SUB(CURDATE(), INTERVAL 1 WEEK))
GROUP BY usr , DATE(tin) , id;

它可以很好地为我提供所需的所有行。但我不知道如何每天和每周插入总和。

当前输出:

Name            Datum               Auftrag Ein         Aus         Zeit
"Manuel Rxxxx"  "Mit 4.11.2015"     A001814 06:58:35    08:45:26    01:46:51
"Manuel Rxxxx"  "Mit 4.11.2015"     Pause   08:45:26    08:59:10    00:13:44
"Manuel Rxxxx"  "Mit 4.11.2015"     A001814 08:59:10    09:06:52    00:07:42
"Manuel Rxxxx"  "Mit 4.11.2015"     Allgeme 09:06:52    10:15:01    01:08:09
"Manuel Rxxxx"  "Mit 4.11.2015"     A001814 10:15:01    10:44:35    00:29:34
"Manuel Rxxxx"  "Mit 4.11.2015"     A001860 10:44:35    12:01:19    01:16:44
"Manuel Rxxxx"  "Mit 4.11.2015"     Pause   12:01:19    13:00:22    00:59:03
"Manuel Rxxxx"  "Mit 4.11.2015"     A001860 13:00:22    15:25:13    02:24:51
"Manuel Rxxxx"  "Mit 4.11.2015"     A001814 15:25:13    16:51:08    01:25:55
"Manuel Rxxxx"  "Don 5.11.2015"     Allgeme 07:00:40    07:32:55    00:32:15
"Manuel Rxxxx"  "Don 5.11.2015"     A001860 07:32:55    07:54:22    00:21:27
"Manuel Rxxxx"  "Don 5.11.2015"     SM Allg 07:54:22    08:41:51    00:47:29
"Manuel Rxxxx"  "Don 5.11.2015"     Pause   08:41:51    08:57:44    00:15:53
"Manuel Rxxxx"  "Don 5.11.2015"     SM Allg 08:57:44    10:59:16    02:01:32
"Manuel Rxxxx"  "Don 5.11.2015"     A001814 10:59:16    11:21:09    00:21:53
"Manuel Rxxxx"  "Don 5.11.2015"     SM Allg 11:21:09    12:00:38    00:39:29
"Manuel Rxxxx"  "Don 5.11.2015"     Pause   12:00:38    13:00:13    00:59:35
"Manuel Rxxxx"  "Don 5.11.2015"     SM Allg 13:00:13    13:15:37    00:15:24
"Manuel Rxxxx"  "Don 5.11.2015"     A001814 13:15:37    15:27:08    02:11:31
"Manuel Rxxxx"  "Don 5.11.2015"     A001860 15:27:08    16:47:01    01:19:53
"Manuel Rxxxx"  "Mon 9.11.2015"     Allgeme 07:00:20    07:02:14    00:01:54
"Manuel Rxxxx"  "Mon 9.11.2015"     A001860 07:02:14    07:48:43    00:46:29
"Manuel Rxxxx"  "Mon 9.11.2015"     Pause   07:48:43    08:03:17    00:14:34
"Manuel Rxxxx"  "Mon 9.11.2015"     A001860 08:03:17    12:00:54    03:57:37
"Manuel Rxxxx"  "Mon 9.11.2015"     Pause   12:00:55    12:59:23    00:58:28
"Manuel Rxxxx"  "Mon 9.11.2015"     A001843 12:59:23    16:48:21    03:48:58
"Manuel Rxxxx"  "Die 10.11.2015"    A001843 07:04:25    08:18:06    01:13:41
"Manuel Rxxxx"  "Die 10.11.2015"    Pause   08:18:06    08:18:46    00:00:40
"Manuel Rxxxx"  "Die 10.11.2015"    A001843 08:18:46    08:45:39    00:26:53
"Manuel Rxxxx"  "Die 10.11.2015"    Pause   08:45:39    09:01:55    00:16:16
"Manuel Rxxxx"  "Die 10.11.2015"    A001843 09:01:55    12:02:49    03:00:54
"Manuel Rxxxx"  "Die 10.11.2015"    Pause   12:02:49    12:58:47    00:55:58
"Manuel Rxxxx"  "Die 10.11.2015"    A001843 12:58:47    13:25:19    00:26:32
"Manuel Rxxxx"  "Die 10.11.2015"    A001814 13:25:19    NULL        NULL

示例数据:http://sqlfiddle.com/#!9/79ed6d/3

任何人都可以给我一个提示吗?

1 个答案:

答案 0 :(得分:1)

SQLFiddle目前无效,但我会尝试向您解释如何实现目标。

首先,您需要通过WEEKOFYEAR()函数知道每个tint日期的周。此值可帮助您分别对每周求和。然后,您可以进行如下查询:

select WEEKOFYEAR(tin) as numWeek,
           DATE(tin) as dateJob, 
           DAYOFWEEK(tin) dayOfWeek,
           usr,
           job,
           (IF( ISNULL(tout), UNIX_TIMESTAMP(), UNIX_TIMESTAMP(tout) ) - UNIX_TIMESTAMP(tin)) as DiffInOut
    from wtime;

现在,您可以使用每个字段(numWeek,usr,dayOfWeek,dateJob和job)对数据进行分组,以获取详细查询:

select numWeek,
       usr,
       dayOfWeek,
       datejob,
       job,
       sum(DiffInOut)
from
  (
    select WEEKOFYEAR(tin) as numWeek,
           DATE(tin) as dateJob, 
           DAYOFWEEK(tin) dayOfWeek,
           usr,
           job,
           (IF( ISNULL(tout), UNIX_TIMESTAMP(), UNIX_TIMESTAMP(tout) ) - UNIX_TIMESTAMP(tin)) as DiffInOut
    from wtime
  ) result
group by numWeek, usr, dayOfWeek, datejob, job

后来建立一个工会,每周只获取信息..

union
select numWeek,
       usr,
       dayOfWeek,
       null,
       null,
       sum(DiffInOut)
from
  (
    select WEEKOFYEAR(tin) as numWeek,
           NULL as dateJob, 
           8 dayOfWeek,
           usr,
           job,
           (IF( ISNULL(tout), UNIX_TIMESTAMP(), UNIX_TIMESTAMP(tout) ) - UNIX_TIMESTAMP(tin)) as DiffInOut
    from wtime
  ) result
group by numWeek, usr, dayOfWeek
order by numWeek, usr, dayOfWeek;

SQLFiddle Example

我希望SQL Fiddle适合你。

结果:

| numWeek |   usr | dayOfWeek |                    datejob |     job | sum(DiffInOut) |
|---------|-------|-----------|----------------------------|---------|----------------|
|      46 | M0005 |         3 | November, 10 2015 00:00:00 | A001942 |          61314 |
|      46 | M0005 |         8 |                     (null) |  (null) |          61314 |
|      46 | M0006 |         3 | November, 10 2015 00:00:00 | A001843 |          61314 |
|      46 | M0006 |         3 | November, 10 2015 00:00:00 | A001814 |              0 |
|      46 | M0006 |         8 |                     (null) |  (null) |          61314 |
|      46 | M0007 |         3 | November, 10 2015 00:00:00 | A001814 |          61314 |
|      46 | M0007 |         3 | November, 10 2015 00:00:00 | .000002 |              0 |
|      46 | M0007 |         8 |                     (null) |  (null) |          61314 |

PD:字段8 dayOfWeek是正确订购周行的一个小技巧。

PD2:我的SQL小提琴示例查询会抛出此结果:

| numWeek |   usr | dayOfWeek |                    datejob |     job | sum(DiffInOut) |
|---------|-------|-----------|----------------------------|---------|----------------|
|      45 | M0006 |         4 | November, 04 2015 00:00:00 | ...ENDE |          50972 |
|      45 | M0006 |         5 | November, 05 2015 00:00:00 | A001860 |           6080 |
|      45 | M0006 |         5 | November, 05 2015 00:00:00 | ...ENDE |         310399 |
|      45 | M0006 |         5 | November, 05 2015 00:00:00 | .000001 |           1935 |
|      45 | M0006 |         5 | November, 05 2015 00:00:00 | .000002 |           4528 |
|      45 | M0006 |         5 | November, 05 2015 00:00:00 | .000031 |          13434 |
|      45 | M0006 |         5 | November, 05 2015 00:00:00 | A001814 |           9204 |
|      45 | M0006 |         8 |                     (null) |  (null) |         396552 |
|      46 | M0006 |         2 | November, 09 2015 00:00:00 | ...ENDE |          51363 |
|      46 | M0006 |         2 | November, 09 2015 00:00:00 | .000001 |            114 |
|      46 | M0006 |         2 | November, 09 2015 00:00:00 | .000002 |           4382 |
|      46 | M0006 |         2 | November, 09 2015 00:00:00 | A001843 |          13738 |
|      46 | M0006 |         2 | November, 09 2015 00:00:00 | A001860 |          17046 |
|      46 | M0006 |         3 | November, 10 2015 00:00:00 | ...ENDE |           1561 |
|      46 | M0006 |         3 | November, 10 2015 00:00:00 | .000002 |           4374 |
|      46 | M0006 |         3 | November, 10 2015 00:00:00 | A001814 |           4924 |
|      46 | M0006 |         3 | November, 10 2015 00:00:00 | A001843 |          25662 |
|      46 | M0006 |         8 |                     (null) |  (null) |         123164 |