PHP复杂时间总和

时间:2014-04-15 15:47:13

标签: php time

我正在尝试编写一个采用如下数据库条目的脚本:

╔════╦═════════╦════════╦══════════╗
║ id ║ user_id ║ action ║   time   ║
╠════╬═════════╬════════╬══════════╣
║  1 ║       1 ║      1 ║ 12:00:00 ║
║  2 ║       1 ║      2 ║ 12:10:00 ║
║  3 ║       1 ║      1 ║ 18:00:00 ║
║  4 ║       1 ║      2 ║ 18:10:00 ║
╚════╩═════════╩════════╩══════════╝

然后找出两个动作之间的区别 1& 2 然后将它们加在一起,这个例子总共会 20:00

我真的不知道从哪里开始,并且似乎无法在网上找到任何有用的东西。

如果有人可以指出我正确的方向,或者将非常感谢任何帮助。

编辑:其他操作可能在数据库(1-7)中,也可能在多个用户中。

Edit2:下面更复杂的示例表,仍然会产生 20:00

的相同示例
╔════╦═════════╦════════╦══════════╗
║ id ║ user_id ║ action ║   time   ║
╠════╬═════════╬════════╬══════════╣
║  1 ║       1 ║      1 ║ 12:00:00 ║
║  2 ║       1 ║      2 ║ 12:10:00 ║
║  3 ║       2 ║      1 ║ 12:30:00 ║
║  4 ║       2 ║      2 ║ 12:40:00 ║
║  5 ║       2 ║      3 ║ 12:50:00 ║
║  6 ║       2 ║      4 ║ 13:00:00 ║
║  7 ║       3 ║      1 ║ 14:00:00 ║
║  8 ║       3 ║      2 ║ 14:10:00 ║
║  9 ║       1 ║      1 ║ 18:00:00 ║
║ 10 ║       1 ║      2 ║ 18:10:00 ║
╚════╩═════════╩════════╩══════════╝

2 个答案:

答案 0 :(得分:1)

讨论后SQL-FIDDLE http://sqlfiddle.com/#!2/8e5ab/5

-

SQL-FIDDLE http://sqlfiddle.com/#!2/ab988/1

SELECT user_id, SUM(time_difference) as time_spent
FROM (    
  SELECT t1.user_id,
  CASE WHEN t1.user_id = t2.user_id 
  THEN time_to_sec(t2.time_duration) - time_to_sec(t1.time_duration) ELSE 0 END time_difference
  FROM T t1 LEFT OUTER JOIN T t2
  ON t1.id = t2.id - 1
  JOIN (SELECT @DIS := 0)R)TAB1
GROUP BY user_id;

这个查询有什么作用?

  • 同一张桌子使用了两次。计算结果在外部SELECT。
  • 中可用
  • 内部SELECT(子查询)执行以下操作:
    • calc时差(t2-t1)
    • 当user_id相同时(user_id = user_id)
    • 但不同的行(id-1)
    • 结果是time_difference
  • 外部SELECT获取time_difference并将其合并

现在,你可以在几秒钟内得到time_spent。 如果您想要确切的结果'20:00',您可以更改第一行以包含时间转换,如下所示:

SELECT user_id, TIME_FORMAT(SEC_TO_TIME(SUM(time_difference)),'%i') as time_spent
better
SELECT user_id, TIME_FORMAT(SEC_TO_TIME(SUM(time_difference)),'%Hh %im') as time_spent

要获取user_id的time_spent,您可以添加

JOIN(SELECT @DIS:= 0)R)TAB1 WHERE user_id = 1

带有时间转换的SQL FIDDLE和WHERE user_id http://sqlfiddle.com/#!2/ab988/9

答案 1 :(得分:1)

这是一个应该让你入门的php方法。假设$ arrQueryResults是来自“SELECT * FROM table ORDER BY user_id,time,action”的DB结果集,使用适合您的数据库的任何语法。

$db = mysqli_connect("server", "username", "password", "database");
$query = "SELECT * FROM action WHERE date = '".$todaysDate."' ORDER BY user_id, time, action";
$result = mysqli_query($db, $query);

while ($arrResult = mysqli_fetch_assoc($result)) { // For each row in the query result
    $user=$arrResult['user_id'];
    $time=strtotime($arrResult['time']); // Converts H:M:S to an integer timestamp
    $action=$arrResult['action'];

    // Add the timestamp for this user and action to track until we have a matched pair
    if ($action == '2') {
        $arrUserAction[$user][$action]=$time;
    }

    if ($action == '5' && isset($arrUserAction[$user]['2'])) {
        if (!isset($arrDiffSums[$user])) {  // If we have no running total for the user yet, create one.
            $arrDiffSums[$user]=$time - $arrUserAction[$user]['2'];
        } else { // IF we have a total for the user already, add to it.
            $arrDiffSums[$user]=$arrDiffSums[$user] + ($time - $arrUserAction[$user]['2']);
        }
        unset($arrUserAction[$user]);  // We just added a sum, now remove our tracking to be ready for the next pair.
    } 
}
print_r($arrDiffSums);

这应该会产生$ arrDiffSums,用户带#secs。在您的第二个表示例中:

array(
  '1' => 1200,
  '2' => 1200,
  '3' => 600
)

可以使用gmdate();PHP - Convert seconds to Hour:Minute:Second)将其转换为H:M:S或其他格式:

foreach ($arrDiffSums as $user => $secs) {
     print "User: ".$user." Sum: ".gmdate("H:i:s", $secs)."\n";
}