Php 从阵列对数据进行分组

Php 从阵列对数据进行分组,php,mysql,arrays,Php,Mysql,Arrays,我有这样一个数据库: id | start | stop | reason 1 | 2017-10-09 08:00:00 | 2017-10-09 08:15:00 | fault 1 2 | 2017-10-09 08:15:00 | 2017-10-09 08:30:00 | fault 2 3 | 2017-10-09 08:30:00 | 2017-10-09 09:00:00 | fault 3 4 | 2017-10

我有这样一个数据库:

id | start               | stop                | reason
1  | 2017-10-09 08:00:00 | 2017-10-09 08:15:00 | fault 1
2  | 2017-10-09 08:15:00 | 2017-10-09 08:30:00 | fault 2
3  | 2017-10-09 08:30:00 | 2017-10-09 09:00:00 | fault 3
4  | 2017-10-09 10:00:00 | 2017-10-09 11:15:00 | fault 1
5  | 2017-10-09 14:00:00 | 2017-10-09 15:00:00 | fault 2
create table faults (id int not null, start timestamp not null, stop timestamp, reason text not null);
insert into faults (id, start, stop, reason) values 
(1, '2017-10-09 08:00:00', '2017-10-09 08:15:00', 'fault 1'),
(2, '2017-10-09 08:15:00', '2017-10-09 08:30:00', 'fault 2'),
(3, '2017-10-09 08:30:00', '2017-10-09 09:00:00', 'fault 3'),
(4, '2017-10-09 10:00:00', '2017-10-09 11:15:00', 'fault 1'),
(5, '2017-10-09 14:00:00', '2017-10-09 15:00:00', 'fault 2'),
(6, '2017-10-09 14:00:00',  NULL                , 'fault 2');
我想使用flot图表制作此数据的饼图,但我需要首先对数据进行分组,并仅以百分比形式显示总持续时间,从而生成如下数组:

0   
label:  "Fault 1"
data:   46.15385
1   
label:  "Fault 2"
data:   38.46154
2   
label:  "Fault 3"
data:   15.38462
我无法对它们进行分组,我以为我可以在_数组中使用,但我在这方面遇到了问题,以下是我到目前为止的代码:-

header('Content-Type: application/json');
$sql = "SELECT * FROM " . STATE_TABLE . " INNER JOIN " . DOWNTIME_TABLE . 
    " ON " . STATE_TABLE . ".reason = " . DOWNTIME_TABLE . ".faultId
    WHERE ('$shiftEnd' > start AND stop > '$shiftStart')
    OR ('$shiftEnd' > start AND stop is null) ORDER BY start DESC";
if ( !($result = $db->sql_query($sql)) )
{
    die('Could not query STATUS_TABLE database');
}
$totalDowntime = 0;
while( $row = $db->sql_fetchrow($result) ) {
    $start = $row['start'];
    $stop = $row['stop'] == null ? $currentTime : $row['stop'];
    $faultStart = $shiftStart > $start ? $shiftStart : $start;
    $faultStop = $stop > $shiftEnd ? $shiftEnd : $stop;

    $duration = get_time_difference($faultStart, $faultStop, 'seconds');

    $totalDowntime += $duration;
    $faults[] = $row;
}
$db->sql_freeresult($result);

$output = array();
$i = 0;
foreach($faults as $fault) {

    $start = $fault['start'];
    $stop = $fault['stop'] == null ? $currentTime : $fault['stop'];
    $description = $fault['description'];   
    $faultStart = $shiftStart > $start ? $shiftStart : $start;
    $faultStop = $stop > $shiftEnd ? $shiftEnd : $stop;

    $duration = get_time_difference($faultStart, $faultStop, 'seconds');

    $percent = ($duration / $totalDowntime) * 100;

    if (in_array($description, $output)) {
        $output[]['data'] += $percent;
    } else {
        $output[$i]['label'] = $description;
        $output[$i]['data'] = $percent;
    }
    $i++;
}

die(json_encode($output));

您不能使用SQL查询对数据进行分组,这样就可以从MySQL中为绘制阵列做好准备了吗

SQL Fiddle:

对于这样的表:

id | start               | stop                | reason
1  | 2017-10-09 08:00:00 | 2017-10-09 08:15:00 | fault 1
2  | 2017-10-09 08:15:00 | 2017-10-09 08:30:00 | fault 2
3  | 2017-10-09 08:30:00 | 2017-10-09 09:00:00 | fault 3
4  | 2017-10-09 10:00:00 | 2017-10-09 11:15:00 | fault 1
5  | 2017-10-09 14:00:00 | 2017-10-09 15:00:00 | fault 2
create table faults (id int not null, start timestamp not null, stop timestamp, reason text not null);
insert into faults (id, start, stop, reason) values 
(1, '2017-10-09 08:00:00', '2017-10-09 08:15:00', 'fault 1'),
(2, '2017-10-09 08:15:00', '2017-10-09 08:30:00', 'fault 2'),
(3, '2017-10-09 08:30:00', '2017-10-09 09:00:00', 'fault 3'),
(4, '2017-10-09 10:00:00', '2017-10-09 11:15:00', 'fault 1'),
(5, '2017-10-09 14:00:00', '2017-10-09 15:00:00', 'fault 2'),
(6, '2017-10-09 14:00:00',  NULL                , 'fault 2');
您可以使用
TIMEDIFF()
函数并按“原因”列分组。
COALESCE()
函数从列表中返回第一个
NOT NULL
值,因此当
stop
为NULL时,可以使用该函数替换当前时间戳:

select 
  reason as label,
  SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(COALESCE(stop, CURRENT_TIMESTAMP), start)))) as data,
  SUM(TIME_TO_SEC(TIMEDIFF(COALESCE(stop, CURRENT_TIMESTAMP), start))) as data_seconds
from faults
group by reason 
order by reason;

|   label |     data | data_seconds |
|---------|----------|--------------|
| fault 1 | 01:30:00 |         5400 |
| fault 2 | 13:23:02 |        48182 |
| fault 3 | 00:30:00 |         1800 |

您不能使用SQL查询对数据进行分组,这样就可以从MySQL中为绘制阵列做好准备了吗

SQL Fiddle:

对于这样的表:

id | start               | stop                | reason
1  | 2017-10-09 08:00:00 | 2017-10-09 08:15:00 | fault 1
2  | 2017-10-09 08:15:00 | 2017-10-09 08:30:00 | fault 2
3  | 2017-10-09 08:30:00 | 2017-10-09 09:00:00 | fault 3
4  | 2017-10-09 10:00:00 | 2017-10-09 11:15:00 | fault 1
5  | 2017-10-09 14:00:00 | 2017-10-09 15:00:00 | fault 2
create table faults (id int not null, start timestamp not null, stop timestamp, reason text not null);
insert into faults (id, start, stop, reason) values 
(1, '2017-10-09 08:00:00', '2017-10-09 08:15:00', 'fault 1'),
(2, '2017-10-09 08:15:00', '2017-10-09 08:30:00', 'fault 2'),
(3, '2017-10-09 08:30:00', '2017-10-09 09:00:00', 'fault 3'),
(4, '2017-10-09 10:00:00', '2017-10-09 11:15:00', 'fault 1'),
(5, '2017-10-09 14:00:00', '2017-10-09 15:00:00', 'fault 2'),
(6, '2017-10-09 14:00:00',  NULL                , 'fault 2');
您可以使用
TIMEDIFF()
函数并按“原因”列分组。
COALESCE()
函数从列表中返回第一个
NOT NULL
值,因此当
stop
为NULL时,可以使用该函数替换当前时间戳:

select 
  reason as label,
  SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(COALESCE(stop, CURRENT_TIMESTAMP), start)))) as data,
  SUM(TIME_TO_SEC(TIMEDIFF(COALESCE(stop, CURRENT_TIMESTAMP), start))) as data_seconds
from faults
group by reason 
order by reason;

|   label |     data | data_seconds |
|---------|----------|--------------|
| fault 1 | 01:30:00 |         5400 |
| fault 2 | 13:23:02 |        48182 |
| fault 3 | 00:30:00 |         1800 |

你的错误是什么?分组有什么问题?作为SQL查询的一部分,并按原因将它们合计在一起。Sari Rahal我没有得到错误,但数据没有分组,并吐出5行而不是3行。Scuzzy我不知道我可以将日期数学作为查询的一部分,我将调查那一点,谢谢你的错误是什么?分组有什么问题?作为SQL查询的一部分,Sari Rahal我没有得到一个错误,但数据没有分组,并吐出5行而不是3行。Scuzzy我不知道我可以将日期数学作为我查询的一部分,我将研究Thanks,这肯定比我的代码干净得多,但它不会将错误加在一起,只显示第一个错误,从我的例子中,我希望:| label | data | u interval | data | u seconds | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |section@Chris哎呀,对不起!我完全忘了用秒来计算时差。我已经编辑了答案,正在进行秒到区间的转换。这非常感谢,我想sql比我想象的强大得多。我想我需要学习它,因为它可能会清理更多我的其他功能。我认为这是一个很好的解决方案,但停止有时可能为空。在这种情况下,我必须使用当前时间来完成计算,或者停止时间可能超过当前班次的结束时间,但我需要该班次的总数,这可以应用到查询中吗?或者我必须恢复到使用php进行查询吗?这当然比我的代码要干净得多,但是它不会将错误添加到一起,只显示第一个错误,从我的例子中,我希望:| label | data | u interval | data | u seconds | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |section@Chris哎呀,对不起!我完全忘了用秒来计算时差。我已经编辑了答案,正在进行秒到区间的转换。这非常感谢,我想sql比我想象的强大得多。我想我需要学习它,因为它可能会清理更多我的其他功能。我认为这是一个很好的解决方案,但停止有时可能为空。在这种情况下,我必须使用当前时间来完成计算,或者停止时间可能超过当前班次的结束时间,但我需要该班次的总数,这可以在查询中使用吗?或者我必须恢复到使用php吗?