小弟能力有限,在做一个小项目时碰见了一个问题,希望大家能帮助一下。数据库cfg_hisdata表用于存放采集到的设备历史参数信息,其中有三个关键字段,TimeH(用于存放6位年月日),TimeL(用于存放6位时分秒),ParamContent(用于存放设备参数)。存放的规则是每整小时存放一次,此外当参数发生变化时也存放一次(精确到秒)。所以对我而言,我从库中得到的数据密度并不均匀。而我需要从查询日期0时到24时将数据以分钟为单位(可以忽略秒)组织,然后传递到前台。
我之前的解决思路大体如下
// 将得到的日期补全,并且计算出天数,用天数乘以1440*60得到秒数
$dateStart = 20120420; // 查询起始日期
$dateEnd = 20120420; // 查询截至日期
$day=(strtotime($dateEnd)-strtotime($dateStart))/3600/24 + 1; // 计算查询天数 $ltime = date('YmdHis', mktime(0, 0, 0, substr($dateStart, 4, 2), substr($dateStart, 6, 2), substr($dateStart, 0, 4))); // 生成查询起始日期的0点0分 for ($i = 0; $i < 1440*60*$day; $i++) // 通过循环生成以秒为单位作value的数组,然后将其作为secArr数组的value
{
$fullTime[] = $ltime;
$ltime = date('YmdHis', strtotime("$ltime + 1 seconds")); // 时间+1秒
}
$secArr = array_fill_keys($fullTime, "");以上是因为数据精度为秒,所以构建一个key为秒的数组之后while($result_va = mysqli_fetch_assoc($query))
{
$temp_data = $result_va['ParamContent'];
$temp_time = $result_va['TimeH'].$result_va['TimeL'];
$secArr[$temp_time] = (float)$temp_data;
if ($cache_d) // 防止复写数组的起始位置
{
$secArr = array_fill($cache_t, (int)$temp_time - $cache_t, $cache_d); // 用前一个有效值填补到当前有效值数组中的空值
}
// 将当前有效值以及时间作为填充值备用
$cache_d = $temp_data;
$cache_t = $temp_time;
}
也就是在遍历查询结果的时候,根据其时标放入之前组织好的秒级数组中,在遍历下一个记录时,用上一个记录的值填补他们之间空余的值。
当这个数组组织好后,我准备再以60为一间隔遍历这个秒级的数组,将其放入分钟为单位的新数组中最后输出。
但是感觉自己的想法太过于繁琐,而且循环次数太多,太不效率。
自己接触开发不久,水平属于入门层次。还请各位指点一下,不胜感激
我之前的解决思路大体如下
// 将得到的日期补全,并且计算出天数,用天数乘以1440*60得到秒数
$dateStart = 20120420; // 查询起始日期
$dateEnd = 20120420; // 查询截至日期
$day=(strtotime($dateEnd)-strtotime($dateStart))/3600/24 + 1; // 计算查询天数 $ltime = date('YmdHis', mktime(0, 0, 0, substr($dateStart, 4, 2), substr($dateStart, 6, 2), substr($dateStart, 0, 4))); // 生成查询起始日期的0点0分 for ($i = 0; $i < 1440*60*$day; $i++) // 通过循环生成以秒为单位作value的数组,然后将其作为secArr数组的value
{
$fullTime[] = $ltime;
$ltime = date('YmdHis', strtotime("$ltime + 1 seconds")); // 时间+1秒
}
$secArr = array_fill_keys($fullTime, "");以上是因为数据精度为秒,所以构建一个key为秒的数组之后while($result_va = mysqli_fetch_assoc($query))
{
$temp_data = $result_va['ParamContent'];
$temp_time = $result_va['TimeH'].$result_va['TimeL'];
$secArr[$temp_time] = (float)$temp_data;
if ($cache_d) // 防止复写数组的起始位置
{
$secArr = array_fill($cache_t, (int)$temp_time - $cache_t, $cache_d); // 用前一个有效值填补到当前有效值数组中的空值
}
// 将当前有效值以及时间作为填充值备用
$cache_d = $temp_data;
$cache_t = $temp_time;
}
也就是在遍历查询结果的时候,根据其时标放入之前组织好的秒级数组中,在遍历下一个记录时,用上一个记录的值填补他们之间空余的值。
当这个数组组织好后,我准备再以60为一间隔遍历这个秒级的数组,将其放入分钟为单位的新数组中最后输出。
但是感觉自己的想法太过于繁琐,而且循环次数太多,太不效率。
自己接触开发不久,水平属于入门层次。还请各位指点一下,不胜感激
if ($cache_d) // 防止复写数组的起始位置
{
$secArr = array_fill($cache_t, (int)$temp_time - $cache_t, $cache_d); // 用前一个有效值填补到当前有效值数组中的空值
}
这就覆盖了
组织秒的数组,主要是因为库中的数据是秒为单位存的,所以每条记录必然能放在这个数组里,然后再筛选库中的数据格式如下:
字段依次为HisID ID TimeH TimeL ParamValue ParamTime ParamContent AlarmLevel
6226042E0101120410191911 6226042E0101 120410 191911 4366693C 2012-04-10 19:19:11 230.411 1
6226042E0101120410191927 6226042E0101 120410 191927 43666748 2012-04-10 19:19:27 230.403 1
6226042E0101120410191957 6226042E0101 120410 191957 4366693C 2012-04-10 19:19:57 230.411 1
6226042E0101120410192012 6226042E0101 120410 192012 43666748 2012-04-10 19:20:12 230.403 1
6226042E0101120410192027 6226042E0101 120410 192027 4366693C 2012-04-10 19:20:27 230.411 1
6226042E0101120410192058 6226042E0101 120410 192058 43666D24 2012-04-10 19:20:58 230.426 1
6226042E0101120410192111 6226042E0101 120410 192111 4366693C 2012-04-10 19:21:11 230.411 1
6226042E0101120410192128 6226042E0101 120410 192128 43666D24 2012-04-10 19:21:28 230.426 1
6226042E0101120410192142 6226042E0101 120410 192142 4366693C 2012-04-10 19:21:42 230.411 1
6226042E0101120410192156 6226042E0101 120410 192156 43666D24 2012-04-10 19:21:56 230.426 1
6226042E0101120410192213 6226042E0101 120410 192213 4366693C 2012-04-10 19:22:13 230.411 1
6226042E0101120410192227 6226042E0101 120410 192227 43666D24 2012-04-10 19:22:27 230.426 1
6226042E0101120410192242 6226042E0101 120410 192242 4366693C 2012-04-10 19:22:42 230.411 1
6226042E0101120410192426 6226042E0101 120410 192426 43666748 2012-04-10 19:24:26 230.403 1
6226042E0101120410192442 6226042E0101 120410 192442 4366693C 2012-04-10 19:24:42 230.411 1
6226042E0101120410192511 6226042E0101 120410 192511 43666748 2012-04-10 19:25:11 230.403 1
6226042E0101120410192541 6226042E0101 120410 192541 43666D24 2012-04-10 19:25:41 230.426 1
6226042E0101120410192558 6226042E0101 120410 192558 43666F18 2012-04-10 19:25:58 230.434 1
6226042E0101120410192612 6226042E0101 120410 192612 43666360 2012-04-10 19:26:12 230.388 1
6226042E0101120410192626 6226042E0101 120410 192626 4366599C 2012-04-10 19:26:26 230.350 1
6226042E0101120410192642 6226042E0101 120410 192642 436657A8 2012-04-10 19:26:42 230.342 1
6226042E0101120410192826 6226042E0101 120410 192826 4366599C 2012-04-10 19:28:26 230.350 1
6226042E0101120410192912 6226042E0101 120410 192912 43665F78 2012-04-10 19:29:12 230.373 1
6226042E0101120410192926 6226042E0101 120410 192926 4366693C 2012-04-10 19:29:26 230.411 1其中主要用到的是TimeH(用于存放6位年月日),TimeL(用于存放6位时分秒),ParamContent(用于存放设备参数。你可以看出,表中的参数存储的时间是不定的(但是整小时必然会存一次)。我先在需要得到一组以整分钟为单位组织的数据,希望你能帮下非常感谢你的回复
于是事情就变得简单了:
查询串写作
$sql =<<< SQL
SELECT * FROM 表 where TimeH=' $dateStart' and
timel in (select max(timel) from 表 where TimeH=' $dateStart' group by left(timel,4))
SQL;
稍加修改就可跨日读取后你只需判断分钟是否连续就可以了