master
vitalif 2010-07-27 05:39:12 +00:00
parent 311ce6b288
commit e9ab8df823
3 changed files with 81 additions and 79 deletions

View File

@ -6,6 +6,7 @@
define ('IN_CONFIG', true);
setlocale(LC_ALL, 'ru_RU.UTF-8');
setlocale(LC_NUMERIC, 'C');
mb_internal_encoding('utf-8');
include_once 'loconfig.php';

151
olap.php
View File

@ -17,19 +17,24 @@ class OLAP
static $sources;
static $current_srcid, $current_src;
static $functions = array(
'year' => array('name' => 'Год', 'time' => true),
'month' => array('name' => 'Месяц', 'time' => true),
'day' => array('name' => 'Дата', 'time' => true),
'weekday' => array('name' => 'День недели', 'time' => true),
'week' => array('name' => '№ недели', 'time' => true),
'year' => array('name' => 'Год', 'time_format' => 'Y', 'sql' => 'SUBSTR($,1,4)'),
'month' => array('name' => 'Месяц', 'time_format' => 'Y-m', 'sql' => 'SUBSTR($,1,7)'),
'day' => array('name' => 'Дата', 'time_format' => 'Y-m-d', 'sql' => 'SUBSTR($,1,10)'),
'weekday' => array('name' => 'День недели', 'time_format' => 'N', 'sql' => 'WEEKDAY($)'),
'week' => array('name' => '№ недели', 'time_format' => 'W', 'sql' => 'WEEK($)'),
'hour' => array('name' => 'Час', 'time_format' => 'H', 'sql' => 'HOUR($)'),
'minute' => array('name' => 'Минута', 'time_format' => 'H:i', 'sql' => 'DATE_FORMAT($, "%k:%i")'),
'second' => array('name' => 'Секунда', 'time_format' => 'H:i:s', 'sql' => 'DATE_FORMAT($, "%k:%i:%s")'),
);
static $aggregates = array(
'count' => array('name' => 'Количество', 'sql' => 'COUNT($)'),
'sum' => array('name' => 'Сумма', 'sql' => 'SUM($)'),
'avg' => array('name' => 'Среднее', 'sql' => 'AVG($)'),
'min' => array('name' => 'Минимум', 'sql' => 'MIN($)'),
'max' => array('name' => 'Максимум', 'sql' => 'MAX($)'),
'stddev' => array('name' => 'Дисперсия', 'sql' => 'STDDEV($)'),
'distinct' => array('name' => 'Значения', 'cell_only' => true),
'count' => array('name' => 'Количество'),
'sum' => array('name' => 'Сумма'),
'avg' => array('name' => 'Среднее'),
'min' => array('name' => 'Минимум'),
'max' => array('name' => 'Максимум'),
'n_uniq' => array('name' => 'Количество уникальных', 'sql' => 'COUNT(DISTINCT $)'),
);
static $specf = array('v_field', 'v_func', 'h_field', 'h_func', 'cell_field', 'cell_aggr', 'cell_func', 'v_sort_dir', 'v_sort_field', 'v_sort_aggr', 'v_sort_func', 'h_sort_dir', 'h_sort_field', 'h_sort_aggr', 'h_sort_func');
@ -109,75 +114,69 @@ class OLAP
exit;
}
$result = mysql_select(self::$current_src['tables'], self::$current_src['fields'], array_merge(self::$current_src['where'], $where), self::$current_src['options'], MS_RESULT);
foreach(self::$specf as $x)
$$x = $request[$x];
$group = array();
$hkeys = array();
$v_v = '';
$v_h = '';
$fetch = self::$current_src['fetch_row'] ? 'mysql_fetch_row' : 'mysql_fetch_assoc';
$code = 'while($r = '.$fetch.'($result)) {';
$fields = array();
$options = array('GROUP BY' => array());
if ($v_field !== '')
{
$code .= '$v_v = ';
if ($v_func !== '')
$code .= 'self::transform_'.$v_func.'(&$r, $v_field);';
else
$code .= '$r[$v_field];';
$v_sql = self::sql_trans_field($v_field, $v_func);
$fields[] = $v_sql.' v_field';
$options['GROUP BY'][] = $v_sql;
}
if ($h_field !== '')
{
$code .= '$v_h = ';
if ($h_func !== '')
$code .= 'self::transform_'.$h_func.'(&$r, $h_field);';
else
$code .= '$r[$h_field];';
$h_sql = self::sql_trans_field($h_field, $h_func);
$fields[] = $h_sql.' h_field';
$options['GROUP BY'][] = $h_sql;
}
$code .= '$v_c = ';
if ($cell_func !== '')
$code .= 'self::transform_'.$cell_func.'(&$r, $cell_field);';
$cell_sql = self::sql_trans_field($cell_field, $cell_func);
if (self::$aggregates[$cell_aggr]['sql'])
$fields[] = str_replace('$', $cell_sql, self::$aggregates[$cell_aggr]['sql']).' cell_field';
else
$code .= '$r[$cell_field];';
$code .= '$hkeys[$v_h] = 1;';
$code .= 'self::aggr_update_'.$cell_aggr.'(&$group[$v_v][$v_h], &$v_c);';
if ($v_field !== '' && $v_sort_aggr !== '' && $v_sort_field !== '')
{
$code .= '$v_vs = ';
if ($v_sort_func !== '')
$code .= 'self::transform_'.$v_sort_func.'(&$r, $v_sort_field);';
else
$code .= '$r[$v_sort_field];';
$code .= 'self::aggr_update_'.$v_sort_aggr.'(&$vsort[$v_v], &$v_vs);';
$do_aggr = true;
$fields[] = $cell_sql.' cell_field';
$options['GROUP BY'][] = $cell_sql;
}
if ($h_field !== '' && $h_sort_aggr !== '' && $h_sort_field !== '')
$result = mysql_select(self::$current_src['tables'], $fields, array_merge(self::$current_src['where'], $where), $options, MS_RESULT);
$group = array();
$hkeys = array();
while ($r = mysql_fetch_assoc($result))
{
$code .= '$v_hs = ';
if ($h_sort_func !== '')
$code .= 'self::transform_'.$h_sort_func.'(&$r, $h_sort_field);';
if ($do_aggr)
call_user_func_array('self::aggr_update_'.$cell_aggr, array(&$group[$r['v_field']][$r['h_field']], &$r['cell_field']));
else
$code .= '$r[$h_sort_field];';
$code .= 'self::aggr_update_'.$h_sort_aggr.'(&$vsort[$v_h], &$v_hs);';
$group[$r['v_field']][$r['h_field']] = $r['cell_field'];
$hkeys[$r['h_field']] = 1;
}
$code .= '}';
eval($code);
if (is_callable("OLAP::aggr_finish_$cell_aggr"))
if ($do_aggr && is_callable('self::aggr_finish_'.$cell_aggr))
foreach ($group as $i => &$r)
foreach ($r as $j => &$c)
call_user_func_array("OLAP::aggr_finish_$cell_aggr", array(&$c));
call_user_func_array('self::aggr_finish_'.$cell_aggr, array(&$c));
if ($v_field !== '' && $v_sort_aggr !== '' && $v_sort_field !== '' && is_callable("OLAP::aggr_finish_$v_sort_aggr"))
foreach ($vsort as $v => &$c)
call_user_func_array("OLAP::aggr_finish_$v_sort_aggr", array(&$c));
if ($v_field !== '' && $v_sort_aggr !== '' && $v_sort_field !== '')
{
$fields = array($v_sql.' v_field');
$vs_sql = self::sql_trans_field($v_sort_field, $v_sort_func);
$fields[] = str_replace('$', $vs_sql, self::$aggregates[$v_sort_aggr]['sql']).' v_sort_field';
$result = mysql_select(self::$current_src['tables'], $fields, array_merge(self::$current_src['where'], $where), array('GROUP BY' => $v_sql), MS_RESULT);
while ($r = mysql_fetch_row($result))
$vsort[$r[0]] = $r[1];
}
if ($h_field !== '' && $h_sort_aggr !== '' && $h_sort_field !== '' && is_callable("OLAP::aggr_finish_$h_sort_aggr"))
foreach ($hsort as $v => &$c)
call_user_func_array("OLAP::aggr_finish_$h_sort_aggr", array(&$c));
if ($h_field !== '' && $h_sort_aggr !== '' && $h_sort_field !== '')
{
$fields = array($h_sql.' v_field');
$hs_sql = self::sql_trans_field($h_sort_field, $h_sort_func);
$fields[] = str_replace('$', $hs_sql, self::$aggregates[$h_sort_aggr]['sql']).' h_sort_field';
$result = mysql_select(self::$current_src['tables'], $fields, array_merge(self::$current_src['where'], $where), array('GROUP BY' => $h_sql), MS_RESULT);
while ($r = mysql_fetch_row($result))
$hsort[$r[0]] = $r[1];
}
$hkeys = array_keys($hkeys);
self::do_sort($hkeys, $hsort, $h_sort_dir);
@ -214,6 +213,18 @@ class OLAP
print $template->parse('admin_olap.tpl');
}
static function sql_trans_field($field, $func)
{
$sql = $field;
if (self::$current_src['fielddescs'][$field]['is_time'] &&
self::$current_src['fielddescs'][$field]['format'] == TS_UNIX &&
(!self::$functions[$func] || self::$functions[$func]['time_format']))
$sql = "FROM_UNIXTIME($sql)";
if (self::$functions[$func])
$sql = str_replace('$', $sql, self::$functions[$func]['sql']);
return $sql;
}
static function do_sort(&$values, &$sortvalues, &$sort_dir)
{
$fn = 'sort';
@ -241,18 +252,22 @@ class OLAP
}
static $is_html_format = true;
static $decimal = '%.3f';
static function field_format($field, $func, $aggr, $value)
{
$o = &self::$current_src['fielddescs'][$field]['options_hash'];
if ($aggr == 'distinct')
{
$r = '';
foreach($value as $k => $n)
$r .= self::field_format($field, $func, false, $k).': '.$n.(self::$is_html_format ? "<br />" : "")."\n";
if ($value)
foreach($value as $k => $n)
$r .= self::field_format($field, $func, false, $k).': '.$n.(self::$is_html_format ? "<br />" : "")."\n";
return $r;
}
elseif ($o && $o[$value])
return $o[$value];
elseif (preg_match('/^-?\d+\.\d+$/s', $value))
return sprintf(self::$decimal, $value);
$fn = self::$is_html_format ? 'htmlspecialchars' : 'addslashes';
return $fn($value);
}
@ -272,17 +287,5 @@ class OLAP
/* Агрегатные функции и преобразования */
static function transform_year(&$row, $field) { return self::o_tsformat('Y', $row, $field); }
static function transform_month(&$row, $field) { return self::o_tsformat('Y-m', $row, $field); }
static function transform_day(&$row, $field) { return self::o_tsformat('Y-m-d', $row, $field); }
static function transform_weekday(&$row, $field) { return self::o_tsformat('N', $row, $field); }
static function transform_week(&$row, $field) { return self::o_tsformat('W', $row, $field); }
static function aggr_update_count(&$n, &$v) { $n++; }
static function aggr_update_sum(&$sum, &$v) { $sum += $v; }
static function aggr_update_avg(&$avg, &$v) { $avg['n']++; $avg['s'] += $v; }
static function aggr_finish_avg(&$avg) { $avg = $avg['s']/$avg['n']; }
static function aggr_update_min(&$min, &$v) { if ($min > $v) $min = $v; }
static function aggr_update_max(&$max, &$v) { if ($max < $v) $max = $v; }
static function aggr_update_distinct(&$d, &$v) { $d[$v]++; }
}

View File

@ -9,19 +9,17 @@ OLAP::$sources = array(
'where' => array(),
'fetch_row' => true,
'fielddescs' => array(
#'ts'
0 => array(
'ts' => array(
'name' => 'Время',
'le_ge' => true,
'is_time' => true,
'format' => TS_UNIX,
'dbname' => 'ts',
),
#'tag'
1 => array(
'tag' => array(
'name' => 'Тег',
'dbname' => 'tag',
'options' => array_merge(array('id' => 0, 'name' => '*'), mysql_select('tags', 'id, name', array('type' => 0))),
'options' => mysql_select('tags', 'id, name', array('type' => 0)),
),
),
),