我目前正在尝试编写一个计时软件,我需要从mysql数据库中获取数据,但我当前的查询(如下所示)有些瑕疵:
一个叫做计时的表有以下几列:
1。员工姓名为varchar,
2。事件名称(" checkin"," checkout")为varchar,
3。该事件的时间戳
我(想)从这个表中检索一个表,它给出了以下列:
1。员工姓名为varchar / string
2。签入时间戳作为时间戳
3。 check-out-timestamp作为时间戳
4。小时(时差)作为int
5。剩余的分钟(时差)为int
如果办理登机手续,但在下次办理登机手续前没有办理退房手续:
退房栏目条目无效(因此雇主看到员工忘记退房了。
如果退房,但在退房前没有办理登机手续:
登记入住栏目无效(因此雇主看到员工忘了办理登机手续。
问题:
如果员工办理登机手续,工作到中午,然后结账休息,稍后重新办理登机手续并在一段时间后结账,我当前的查询仅计算第一次办理登机手续和最后一次退房的时差。这显然是错误的......
另外:它仅在这些签到和结账时计算这些 发生在一个日期内,这不是一个大问题(但是 想象一下在午夜之前和午夜之后的计时...... 目前不可能)
第一次登记入住和退房之间的登记入住和退房手续甚至都没有显示在任何地方(因此缺少行)......
我当前的(错误的)查询:
SELECT Employee,
MIN(CASE WHEN event = 'checkin' THEN timestamp END) as checkin,
MAX(CASE WHEN event = 'checkout' THEN timestamp END) as checkout,
TIMESTAMPDIFF(HOUR,
MIN(CASE WHEN event = 'checkin' THEN timestamp END),
MAX(CASE WHEN event = 'checkout' THEN timestamp END)
) AS hours,
MOD(TIMESTAMPDIFF(MINUTE,
MIN(CASE WHEN event = 'checkin' THEN timestamp END),
MAX(CASE WHEN event = 'checkout' THEN timestamp END)
), 60) AS minutes
FROM timekeeping AS T
WHERE employee LIKE 'Bobby Brown'
GROUP BY Date(timestamp) ORDER BY timestamp DESC;
修改
示例:
让我们说员工在6点钟办理登机手续,工作,12点休息,但不办理退房手续13点回来,办理登机手续,工作到15点,退房。我的查询只返回6到15之间的一个条目
答案 0 :(得分:0)
我通常不会做这些类型的子查询,但值得一试:
SELECT T_in.Employee
, T_in.timestamp AS checkin
, (SELECT MIN(T_out.timestamp)
FROM timekeeping AS T_out
WHERE T_out.employee = T_in.employee
AND T_out.timestamp > T_in.timestamp
AND T_out.event = 'checkout'
) AS checkout
FROM timekeeping AS T_in
WHERE T_in.employee LIKE 'Bobby Brown'
AND T_in.event = 'checkin'
ORDER BY checkin
;
要获得时间跨度,请执行以下操作:
SELECT Employee, checkin, checkout
, ((TIME_TO_SEC(checkout) - TIME_TO_SEC(checking)) / 60)
+ (DATEDIFF(DATE(checkout), DATE(checkin)) * 60 * 24)
AS `minutes`
FROM (
[the query above minus the ;]
) AS subQ
;
编辑:添加实际分钟计算;请注意,60 * 24是一天中的分钟数(如果跨越午夜,TIME_TO_SEC()减法部分将为负数。)
Edit2:这应该有助于进入内部场景。
( SELECT T_in.Employee
, T_in.timestamp AS checkin
, (SELECT IF(T_out.event = 'checkout', T_out.timestamp, NULL)
FROM timekeeping AS T_out
WHERE T_out.employee = T_in.employee
AND T_out.timestamp > T_in.timestamp
ORDER BY T_out.timestamp ASC
LIMIT 1
) AS checkout
FROM timekeeping AS T_in
WHERE T_in.employee LIKE 'Bobby Brown'
AND T_in.event = 'checkin'
ORDER BY checkin ) AS sub1
UNION (
SELECT T_out2.Employee
, (SELECT IF(T_in2.event = 'checkin', T_in2.timestamp, NULL)
FROM timekeeping AS T_in2
WHERE T_in2.employee = T_out2.employee
AND T_in2.timestamp < T_out2.timestamp
ORDER BY T_in2.timestamp DESC
LIMIT 1) AS checkin
, T_out2.timestamp AS checkout
FROM timekeeping AS T_out2
WHERE T_out2.employee LIKE 'Bobby Brown'
AND T_out2.event = 'checkout'
HAVING checkin IS NULL ) AS sub2
;
在平板电脑上完成最后一次编辑,所以我希望这是正确的。 ;)