MySQL - 对项目的时间条目进行分组和汇总

时间:2016-05-26 12:14:39

标签: php mysql

我从toggl.com获得了这些时间记录数据,我需要将报告的格式与它们提供的内容略有不同 - 这就是为什么我认为我会尝试将csv数据导入MySQL并对其进行格式化我自己通过MySQL和PHP等但我几乎在开始之前就陷入了困境 - 将数据导入MySQL,所以现在我需要在html表中输出它...不知何故。

我有这些数据:

+-----------+---------------------------------------+------------+----------+
|  Project  |                 Task name             |    Date    | Duration |
+-----------+---------------------------------------+------------+----------+
| Project 1 | Task name 2                           | 2016-05-12 | 00:22:03 |
| Project 2 | Task name 1                           | 2016-05-12 | 00:04:24 |
| Project 2 | Task name 1                           | 2016-05-12 | 00:06:27 |
| Project 1 | 3. correction                         | 2016-05-13 | 00:08:00 |
| Project 1 | Small correction                      | 2016-05-13 | 00:02:02 |
| Project 1 | Last correction                       | 2016-05-16 | 00:05:36 |
| Project 1 | Created low-res                       | 2016-05-16 | 00:04:21 |
| Project 2 | Layout                                | 2016-05-24 | 00:27:45 |
| Project 2 | Layout                                | 2016-05-25 | 01:00:00 |
| Project 2 | Finishing                             | 2016-05-25 | 00:15:48 |
+-----------+---------------------------------------+------------+----------+

我梦想实现的是每个项目的数据如下:

Project 2  
-----------------------------------------------------
Date            Tasks                     Total
-----------------------------------------------------
12/05/16        Task name 1               00:10:51
24/05/16        Layout                    00:27:45
25/05/16        Layout, Finishing         01:15:48
-----------------------------------------------------
Project 2 total                           01:54:24

因此,对于每个项目,每个日期都应该有自己的行,包括日期任务名称 (逗号分隔)和日期

持续时间的总和

然后是项目总数。

任何帮助都将非常感谢!! : - )

修改

SELECT 
     Project,
     `Task name`,
     Date,
     Duration,
     SEC_TO_TIME( SUM( TIME_TO_SEC( `Duration` ) ) ) AS TotalDuration 
     FROM timerecordings
     GROUP BY Project, Date, `Task name` WITH ROLLUP

给我(不要看日期和时间格式化,这样做很棒):

+-----------+------------------+------------+----------+----------+
| Project 1 | Task name 2      | 12/05/2016 | 00.22.03 | 00.22.03 |
| Project 1 | NULL             | 12/05/2016 | 00.22.03 | 00.22.03 |
| Project 1 | 3. correction    | 13/05/2016 | 00.08.00 | 00.08.00 |
| Project 1 | Small correction | 13/05/2016 | 00.02.02 | 00.02.02 |
| Project 1 | NULL             | 13/05/2016 | 00.02.02 | 00.10.02 |
| Project 1 | Created low-res  | 16/05/2016 | 00.04.21 | 00.04.21 |
| Project 1 | Last correction  | 16/05/2016 | 00.05.36 | 00.05.36 |
| Project 1 | NULL             | 16/05/2016 | 00.05.36 | 00.09.57 |
| Project 1 | NULL             | NULL       | 00.05.36 | 00.42.02 |
| Project 2 | Task name 1      | 12/05/2016 | 00.04.24 | 00.10.51 |
| Project 2 | NULL             | 12/05/2016 | 00.04.24 | 00.10.51 |
| Project 2 | Layout           | 24/05/2016 | 00.27.45 | 00.27.45 |
| Project 2 | NULL             | 24/05/2016 | 00.27.45 | 00.27.45 |
| Project 2 | Finishing        | 25/05/2016 | 00.15.48 | 00.15.48 |
| Project 2 | Layout           | 25/05/2016 | 01.00.00 | 01.00.00 |
| Project 2 | NULL             | 25/05/2016 | 01.00.00 | 01.15.48 |
| Project 2 | NULL             | NULL       | 01.00.00 | 01.54.24 |
| NULL      | NULL             | NULL       | 01.00.00 | 02.36.26 |
+-----------+------------------+------------+----------+----------+

3 个答案:

答案 0 :(得分:0)

必须是

之类的东西
select date, taskName, sum(duration) from tasksTable where Project = "Project 2" group by date

但是如何添加时间,以及如何在一个字段中获取所有taskNames仍然需要进行实验。

答案 1 :(得分:0)

您可以使用GROUP_CONCAT聚合函数将所有任务名称组合在一个字符串中。使用SEPARATOR关键字定义分隔符(默认值:',')。如果您不希望多次列出相同的任务,请使用DISTINCT

对于一个项目:

SELECT Date,
  GROUP_CONCAT(DISTINCT `Task name` SEPARATOR ', ') AS Task,
  SEC_TO_TIME(SUM(TIME_TO_SEC(Duration))) AS Total
FROM timerecordings r
WHERE Project = 'Project 2'
GROUP BY Date WITH ROLLUP;

对于所有项目:

SELECT SELECT Project, Date, 
  GROUP_CONCAT(DISTINCT `Task name` SEPARATOR ', ') AS Task,
  SEC_TO_TIME(SUM(TIME_TO_SEC(Duration))) AS Total
FROM timerecordings r
GROUP BY Project, Date WITH ROLLUP;

sqlfiddle

答案 2 :(得分:0)

只是为了让你得到我的最终结果:

 <?php
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "timerecordings";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT 
            IFNULL (Project,'All Projects') Project,
            IFNULL (Date,'Project total') Date,
            GROUP_CONCAT(DISTINCT `Task name` SEPARATOR ', ') AS Task,
            SEC_TO_TIME(SUM(TIME_TO_SEC(Duration))) AS Total
            FROM timerecordingstable r
            GROUP BY Project, Date WITH ROLLUP;           
        ";
$result = $conn->query($sql);

$data = array();

while($row = $result->fetch_assoc()) {
    $projectname = $row["Project"];
    if (!array_key_exists($projectname, $data)) {
        $data[$projectname] = array();
    }
    $data[$projectname][] = $row;
}

foreach ($data as $projectname => $rows) {
    if($projectname != 'All Projects'){
        echo '<h1>', $projectname, '</h1>';

        echo '<table class="time-table"><tr class="table-header"><th>Date</th><th>Tasks</th><th>Time used</th><tr>';

        foreach ($rows as $row) {
            //Convert Total into seconds
            $str_time = $row["Total"];
            $str_time = preg_replace("/^([\d]{1,2})\:([\d]{2})$/", "00:$1:$2", $str_time);
            sscanf($str_time, "%d:%d:%d", $hours, $minutes, $seconds);
            $time_seconds = $hours * 3600 + $minutes * 60 + $seconds;

            // Round to nearest minute
            $time_seconds = round($time_seconds/60)* 60;

            $hours = floor($time_seconds / 3600); //Hours
            $minutes = floor(($time_seconds / 60) % 60); //Minutes

            //Convert minutes to two decimal number (like 15 minutes = 0.25 hour etc.)
            $minutes = $minutes / 60;
            $minutes = round($minutes,2);
            $minutes = $minutes*100;

            $seconds = $time_seconds % 60; //Seconds - I don't use it but kept to show it's possible

            //Loop each row
            if($row["Date"] == 'Project total'){
                echo '<tr class="table-footer"><td>', $row["Date"] , '</td><td>' , '&nbsp;' , '</td><td>' , $hours, ',',$minutes, ' hour(s)</td></tr>';
            } else {
                $prettyDate = DateTime::createFromFormat('Y-m-j', $row["Date"]);
                echo '<tr><td>', $prettyDate->format('d-m-Y') , ':</td><td>' , $row["Task"] , '</td><td>' , $hours, ',',$minutes, ' hour(s)</td></tr>';    
            }
        }

        echo '</table>';
    }
}

$conn->close();

?> 

结果:

<h1>Project 1</h1>
<table class="time-table">
  <tr class="table-header">
    <th>Date</th>
    <th>Tasks</th>
    <th>Time used</th>
  <tr>
  <tr>
    <td>12-05-2016:</td>
    <td>Task name 2</td>
    <td>0,37 hour(s)</td>
  </tr>
  <tr>
    <td>13-05-2016:</td>
    <td>3. correction, Small correction</td>
    <td>0,17 hour(s)</td>
  </tr>
  <tr>
    <td>16-05-2016:</td>
    <td>Last correction, Created low-res</td>
    <td>0,17 hour(s)</td>
  </tr>
  <tr class="table-footer">
    <td>Project total</td>
    <td>&nbsp;</td>
    <td>0,70 hour(s)</td>
  </tr>
</table>
<h1>Project 2</h1>
<table class="time-table">
  <tr class="table-header">
    <th>Date</th>
    <th>Tasks</th>
    <th>Time used</th>
  <tr>
  <tr>
    <td>12-05-2016:</td>
    <td>Task name 1</td>
    <td>0,18 hour(s)</td>
  </tr>
  <tr>
    <td>24-05-2016:</td>
    <td>Layout</td>
    <td>0,47 hour(s)</td>
  </tr>
  <tr>
    <td>25-05-2016:</td>
    <td>Layout, Finishing</td>
    <td>101,27 hour(s)</td>
  </tr>
  <tr class="table-footer">
    <td>Project total</td>
    <td>&nbsp;</td>
    <td>101,90 hour(s)</td>
  </tr>
</table>