【问题标题】:Get total hours with PHP & MySQL使用 PHP 和 MySQL 获取总小时数
【发布时间】:2018-09-19 04:41:26
【问题描述】:

我有下表

id | user_id | date                 | status
1  |    53   | 2018-09-18 06:59:54  | 1
2  |    62   | 2018-09-18 07:00:16  | 1
3  |    53   | 2018-09-18 09:34:12  | 2
4  |    53   | 2018-09-18 12:16:27  | 1
5  |    53   | 2018-09-18 18:03:19  | 2
6  |    62   | 2018-09-18 18:17:41  | 2

我想获取总工作时间(来自日期范围)并按 user_id 分组

更新

系统不“要求”退房,所以如果只有一个值,我们可以设置默认退房时间,比如 19:00:00?如果没有,我可以在每天 21:00:00 检查是否没有结帐时间在 19:00:00 手动插入它

更新 2

我在“状态”表中添加了一个新字段,因此第一次签入日期的状态 = 1,每第二次签入状态 = 2

因此,如果用户在一天中第三次签到,则状态将再次变为 1,以此类推。

我希望这会让事情变得更容易

谢谢

【问题讨论】:

  • 你尝试了什么?
  • 请更新示例数据,同时显示状态值。
  • @MadhurBhaiya 已更新

标签: php mysql datetime


【解决方案1】:

如果一天内发生多次入住和退房,对于用户:

  • 利用Correlated Subquery,我们可以为每个“checkin_time”找到对应的“checkout_time”。
  • 另外,注意Ifnull()Timestamp()等函数的使用,在没有对应条目的情况下,默认“checkout_time”为19:00:00
  • 然后,将这个增强的数据集视为Derived Table,我们根据user_iddate 对数据集进行分组。日期(yyyy-mm-dd)可以使用Date()函数确定。
  • 最终,将Timestampdiff() 函数与Sum 聚合结合使用,以确定user_id 在特定日期的总工作秒数。
  • 您可以轻松地将这些总秒数转换为小时数(在您的应用程序代码中或在查询本身中(将秒数除以 3600)。
  • 我更喜欢使用秒计算的原因,因为 Timestampdiff() 函数只返回整数。因此,在多次签入/签出的情况下可能会出现截断错误。

使用以下查询(将your_table 替换为您的实际表名):

SELECT inner_nest.user_id, 
       DATE(inner_nest.checkin_time) AS work_date, 
       SUM(TIMESTAMPDIFF(SECOND, 
                         inner_nest.checkin_time,
                         inner_nest.checkout_time)) AS total_work_seconds  
FROM 
(
  SELECT t1.user_id, 
         t1.date as checkin_time, 
         t1.status, 
         IFNULL( ( 
                  SELECT t2.date 
                  FROM your_table AS t2 
                  WHERE t2.user_id = t1.user_id 
                    AND t2.status = 2 
                    AND t2.date > t1.date 
                    AND DATE(t2.date) = DATE(t1.date) 
                  ORDER BY t2.date ASC LIMIT 1
                 ), 
                 TIMESTAMP(DATE(t1.date),'19:00:00')
               ) AS checkout_time 
  FROM `your_table` AS t1 
  WHERE t1.status = 1
) AS inner_nest 
GROUP BY inner_nest.user_id, DATE(inner_nest.checkin_time)

补充:以下解决方案适用于单次入住,并在同一日期相应退房的情况。

  • 您首先需要根据user_iddate 对数据集进行分组。日期(yyyy-mm-dd)可以使用Date()函数确定。

  • 现在使用 Min()Max() 等聚合函数来查找 user_id 在特定日期的开始和结束时间。

  • 最终,使用Timestampdiff() 函数确定user_id 在特定日期的工作时间(结束时间和开始时间之间的差异)

尝试以下查询(将your_table 替换为您的实际表名):

SELECT user_id, 
       DATE(`date`) AS working_date, 
       TIMESTAMPDIFF(HOUR, MIN(`date`), MAX(`date`)) AS working_hours 
FROM your_table 
GROUP BY 
  user_id, 
  DATE(`date`)

【讨论】:

  • 我相信如果用户每天有一次签入和签出,这一项工作。如果在您的查询获取第一次签入和最后一次签出的日期期间有多个签入和签出,并计算小时差。我们白天确实有多次入住和退房,我们需要计算每次入住和退房之间的总和
  • @Andr 同意了。请使用此详细信息编辑您的问题。它被错过了。我将制定一个单独的查询。
  • @Andr 还有,数据是否确保对于特定日期的每次签入,总是在同一日期签出?
  • 请不要将指向您自己答案的链接放在 cmets 部分。这肯定是违反礼节的。
  • @MadhurBhaiya 你是最棒的!很好的查询!
【解决方案2】:

使用TIMESTAMPDIFF函数

查询更像:

SELECT t1.user_id, TIMESTAMPDIFF(HOUR,t1.date,t2.date) as difference
FROM your_table t1
       INNER JOIN your_table t2 on t1.user_id = t2.user_id
Group By t1.user_id

您可以将此视为偏好TimeStampDiff

【讨论】:

    猜你喜欢
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多