Записки ниже не касаются тех, у кого значения в таблицу пишутся регулярно и с повторами.
У меня это, к сожалению, не так.
Штатная функция gethistoryavg возвращает среднее арифметическое от значений в периоде, подразумевая равноправие всех отсчетов значений.
Предлагается вместо этого использовать средневзвешенное по времени, где вес значения зависит от длительности его действия.
Итог виден тут (бралась температура за сутки, медленно меняющаяся около нуля):
2019-03-24 14:51:00
2019-03-23 14:51:00
getHistoryAvgMy=0.3879
getHistoryAvg=-0.301436781609196
Вычисленное средневзвешенное значение = 0.38, среднее getHistoryAvg = -0.30
Вот код функции:
/**
* getHistoryAvgMy
*
* Return AVG data
*
* @access public
*/
function getHistoryAvgMy($varname, $start_time, $stop_time = 0) {
if ($start_time <= 0) $start_time = (time() + $start_time);
if ($stop_time <= 0) $stop_time = (time() + $stop_time);
// Get hist val id
$pvalue = getHistoryValueId($varname);
if (defined('SEPARATE_HISTORY_STORAGE') && SEPARATE_HISTORY_STORAGE == 1) {
$table_name = createHistoryTable($pvalue);
} else {
$table_name = 'phistory';
}
// Получить количество записей за нужный период времени
$arr_s = SQLSelectOne("SELECT COUNT(ID) as COUNT_ID FROM $table_name ".
"WHERE VALUE_ID=".$pvalue." and not value is null ".
"AND ADDED between '".date('Y-m-d H:i:s', $start_time)."' AND '".date('Y-m-d H:i:s', $stop_time)."'");
// Взять это количество записей +1
$arr_s = SQLSelect("SELECT * FROM $table_name WHERE VALUE_ID=".$pvalue." and not value is null ".
" AND ADDED<='".date('Y-m-d H:i:s', $stop_time)."' ORDER BY ADDED DESC LIMIT 0 , ".(1+$arr_s['COUNT_ID']));
$tmr2 = $stop_time;
// Переберем весь массив
foreach($arr_s as $s) {
$tmr1 = $tmr2;
$tmr2 = strtotime($s['ADDED']);
// Ограничить началом
if ($tmr2<$start_time)
$tmr2 = $start_time;
// Двигаясь вниз по массиву времени складывать отрезки
//echo(date('H:i:s', $tmr1).' - '.date('H:i:s', $tmr2).' = '.($tmr1 - $tmr2).'c t='.$s['VALUE'].'<br>');
$tmr_mem = $tmr_mem + $tmr1 - $tmr2;
$ss = $ss + $s['VALUE']*($tmr1 - $tmr2);
}
$avg = $ss / $tmr_mem ;
if (!$avg)
return false;
return $avg;
}
Проверялось в экселе по этой строке:
echo(date('H:i:s', $tmr1).' - '.date('H:i:s', $tmr2).' = '.($tmr1 - $tmr2).'c t='.$s['VALUE'].'<br>');
Домодедово, Россия
На форуме: xor