1

我有一个包含以下类型的登录/注销数据的表。我正在尝试创建每天工作小时数的报告。我无法破解的第一件事是为 mysql 中的用户和包含名称、日期、时间跨度的数组选择登录/注销对。

所以对于我正在查看的查询:

SELECT * FROM timestamps
WHERE name = $namevar 

那么我在查询中添加什么来选择和添加对呢?

示例数据:(SQLFiddle

    id     |      date_time      |    field1    |    field2    |  firstname   |    in_out    |   special
VARCHAR(3) |       DATETIME      | varchar(255) | varchar(255) | varchar(255) | varchar(255) | varchar(255)
-----------+---------------------+--------------+--------------+--------------+--------------+-------------
    104    | 2012-06-11 17:14:43 |       2      |       1      | Joshua W     |       O      |      0
    106    | 2012-06-11 17:15:32 |       2      |       1      | Zedfried     |       O      |      0
    215    | 2012-06-11 18:12:14 |       2      |       1      | Chris No     |       O      |      0
    237    | 2012-06-11 18:13:32 |       2      |       1      | Craig St     |       O      |      0
    237    | 2012-06-12 06:49:05 |       2      |       1      | Craig St     |       I      |      0
    026    | 2012-06-12 06:50:32 |       2      |       1      | Renaldo      |       I      |      0
    079    | 2012-06-12 06:50:44 |       2      |       1      | Herman A     |       I      |      0
    104    | 2012-06-12 06:52:44 |       2      |       1      | Joshua W     |       I      |      0
    079    | 2012-06-12 12:28:46 |       2      |       1      | Herman A     |       O      |      0
    079    | 2012-06-12 12:28:53 |       2      |       1      | Herman A     |       I      |      0
    104    | 2012-06-12 12:32:51 |       2      |       1      | Joshua W     |       O      |      0
    104    | 2012-06-12 12:32:59 |       2      |       1      | Joshua W     |       I      |      0
    079    | 2012-06-12 18:19:57 |       2      |       1      | Herman A     |       O      |      0
    104    | 2012-06-12 22:12:25 |       2      |       1      | Joshua W     |       O      |      0
    237    | 2012-06-12 22:12:57 |       2      |       1      | Craig St     |       O      |      0
    079    | 2012-06-13 06:47:21 |       2      |       1      | Herman A     |       I      |      0

最终报告将如下所示

Emp Code    Name    Sun Mon     Tues        Wed     Thurs           Fri     Sat Total           

x 2                 std     OT1 std     OT1 Std     OT1 std     OT1 std     OT1 Std     OT1 std     OT1     OT 2        Grand

AE0001  B SKAKANE   2.25    0   8.75    3    8.75   3    8.75   3    8.75   2    5.00   2   8.75     40.00   21.75   2.25    64.00 
AE006   J MTOLO     8.75         8.75   1    8.75        8.75   1    5.00   5    40.00      7.00     -       47.00 
AE007   B  ZACA     8.75    1    8.75   2    8.75   2    8.75   2                35.00      7.00     -       42.00 
AE0013  C NEHUMBA   8.75         8.75        8.75   1    8.75        5.00   2    40.00      3.00     -       43.00 

更新:

http://sqlfiddle.com/#!2/fabb5/2/1

此解决方案适用于上面的 mysql fiddle,但不适用于我的程序:

$query = $this -> db -> query('
set @num := 0, @in_out := \'\';

select emp_in.id,
  emp_in.in_time,
  emp_out.out_time
from 
(
  select id, in_out, date_time in_time, 
     @num := if(@in_out = in_out, @num + 1, 1) as row_number,
     @in_out := in_out as dummy
  from fingerevent
  where in_out = \'I\'
  order by date_time, id
) emp_in
join
(
  select id, in_out, date_time out_time,
     @num := if(@in_out = in_out, @num + 1, 1) as row_number,
     @in_out := in_out as dummy
  from fingerevent
  where in_out = \'O\'
 order by date_time, id
) emp_out
  on emp_in.id = emp_out.id

  and emp_in.row_number = emp_out.row_number
order by emp_in.id, emp_in.in_time

');

错误:

Error Number: 1064

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select emp_in.id, emp_in.in_time, emp_out.out_time from ( select id,' at line 3

我希望这个问题很清楚。有什么我可以澄清的,请告诉我。

4

1 回答 1

0

假设包含数据的表被调用timestamps,这个查询应该给你一些有用的结果:

SELECT `c`.`day`, `b`.`date`, `b`.`id`, `b`.`firstname`, HOUR(`b`.`duration`) + (FLOOR((MINUTE(`b`.`duration`) / 60) * 4) / 4) AS `hours_worked`
FROM (
  SELECT `a`.`id`, `a`.`firstname`, `a`.`date`, SEC_TO_TIME(SUM(TIME_TO_SEC(`a`.`duration`))) AS `duration`
  FROM (
    SELECT `i`.`id`, `i`.`firstname`, TIMEDIFF(COALESCE(MIN(`o`.`date`), ADDTIME(TIMESTAMP(DATE(MAX(`i`.`date`))), '23:59:59')), MAX(`i`.`date`)) AS `duration`, DATE(`i`.`date`) AS `date`
    FROM `timestamps` `i`
    LEFT JOIN `timestamps` `o`
      ON `i`.`id` = `o`.`id` AND `i`.`type` != `o`.`type` AND DATE(`i`.`date`) = DATE(`i`.`date`) AND `i`.`date` < `o`.`date`
    WHERE `i`.`type` = 'I'
    GROUP BY `i`.`date`
  ) `a`
  GROUP BY `a`.`id`, `a`.`date`
) `b`
JOIN `days` `c`
  ON DAYOFWEEK(`b`.`date`) = `c`.`id`
ORDER BY `b`.`date`, `b`.`id`

...其中表days是从星期日开始的星期几名称的 1 索引表。

如果您想将其缩小到特定的日期范围,请更改

WHERE i.type = 'I'

WHERE i.type = 'I' AND i.date BETWEEN <startdate> AND <enddate>

此查询做出 3 个假设:

  • 为了将持续时间减少到最接近的 15 分钟(您的示例报告显示8.752.25),我已四舍五入。
  • 如果有O条目的一天没有条目I,则假设员工在当天 23:59:59 下班。
  • O条目但没有I条目的一天将被忽略。

看到它工作

于 2012-09-18T08:08:05.887 回答