Rounding, joins

master
Vitaliy Filippov 2017-12-07 17:11:40 +03:00
parent 1e4ded1796
commit b8eef8a695
3 changed files with 98 additions and 17 deletions

View File

@ -68,6 +68,7 @@ class OLAP
'max' => array('name' => 'Максимум', 'sql' => 'MAX($)'),
'stddev' => array('name' => 'Дисперсия', 'sql' => 'STDDEV($)'),
'n_uniq' => array('name' => 'Количество уникальных', 'sql' => 'COUNT(DISTINCT $)'),
'sum_rnd' => array('name' => 'Сумма округлённая', 'sql' => 'ROUND(SUM($))'),
);
static $group_types = array(
'tables' => 'Несколько таблиц',
@ -80,7 +81,7 @@ class OLAP
var $request;
var $current_srcid, $current_src;
var $time_start, $nfields, $build, $csv;
var $where, $where_nosql, $group_fields, $cell;
var $tables, $where, $where_nosql, $group_fields, $cell;
var $is_html_format = true;
var $add_spanned;
var $graph_scale = 600; /* пикселей */
@ -161,10 +162,15 @@ class OLAP
foreach ($v['options'] as &$o)
$v['options_hash'][$o['id']] = $o['name'];
}
if (is_object($v['sql']) && get_class($v['sql']) === 'Closure')
{
$v['sql'] = $v['sql']($this);
}
}
unset($v);
// читаем параметры запроса
$this->tables = array();
$this->where = array();
$this->where_nosql = array();
$this->group_fields = array();
@ -187,6 +193,8 @@ class OLAP
}
if (!$fd || !strlen($v))
continue;
if (!empty($fd['join']))
$this->tables += $fd['join'];
$this->request[$k] = $v;
if (!empty($fd['is_time']))
$v = VMXTemplate::timestamp($v, $this->current_src['fielddescs'][$f]['format']);
@ -388,15 +396,16 @@ class OLAP
$group_fields = $output[0]['group_by'];
$fields = array();
$group_by = array();
$tables = array();
foreach ($group_fields as $i => &$v)
{
$v['sql'] = $this->sql_trans_field($v['field'], $v['func']);
$v['sql'] = $this->sql_trans_field($v['field'], $v['func'], $tables);
$v['keys'] = array();
$fields[] = $v['sql'].' f'.$i;
$group_by[] = $v['sql'];
}
$sql = $this->sql_trans_field($field, $func);
$sql = $this->sql_trans_field($field, $func, $tables);
$fields[] = str_replace('$', $sql, self::$aggregates[$aggr]['sql']).' c';
$code = 'while($r = $result->fetch_assoc()) { ';
@ -410,7 +419,7 @@ class OLAP
$code .= '}';
$result = $this->mysql()->select(
$this->current_src['tables'], $fields,
$this->current_src['tables'] + $this->tables + $tables, $fields,
array_merge($this->current_src['where'], $this->where),
array('GROUP BY' => $group_by),
MS_RESULT
@ -876,9 +885,11 @@ class OLAP
return $c;
}
function sql_trans_field($field, $func)
function sql_trans_field($field, $func, &$tables)
{
$fd = &$this->current_src['fielddescs'][$field];
if (!empty($fd['join']))
$tables += $fd['join'];
if (empty($field) && $field !== '0')
$sql = '1';
else
@ -987,6 +998,18 @@ class OLAP
$aggr += $value;
}
// Сумма округлённая - обновление
static function aggr_update_sum_rnd(&$aggr, &$value)
{
$aggr += $value;
}
// Сумма округлённая - обновление
static function aggr_finish_sum_rnd(&$aggr)
{
$aggr = round($aggr);
}
// Среднее - обновление
static function aggr_update_avg(&$aggr, &$value)
{

View File

@ -1,10 +1,5 @@
<?php
function v2tags_get_tags()
{
return mysql_select('tags', 'id, name', array('type' => 0));
}
OLAP::$sources = array(
'mediawiki_history' => array(
'id' => 'mediawiki_history',
@ -36,7 +31,10 @@ OLAP::$sources = array(
),
'tag' => array(
'name' => 'Тег',
'options' => 'v2tags_get_tags',
'options' => function($olap)
{
return $olap->mysql()->select('tags', 'id, name', array('type' => 0));
}
),
),
),
@ -76,15 +74,41 @@ OLAP::$sources = array(
'bugzilla' => array(
'id' => 'bugzilla',
'name' => 'Время Bugzilla',
'tables' => array('t' => 'bugs3.longdescs', 'p' => 'bugs3.profiles'),
'tables' => array(
't' => 'bugs3.longdescs',
'p' => [ 'INNER', 'bugs3.profiles', [ 'p.userid=t.who' ] ],
'b' => [ 'INNER', 'bugs3.bugs', [ 'b.bug_id=t.bug_id' ] ],
'pr' => [ 'INNER', 'bugs3.products', [ 'pr.id=b.product_id' ] ],
'c' => [ 'INNER', 'bugs3.components', [ 'c.id=b.component_id' ] ],
'bt' => [ 'LEFT', 'bugs3.cf_bug_type', [ 'bt.id=b.cf_bug_type' ] ],
),
'fields' => 'p.login_name, t.bug_when, t.work_time',
'where' => array('t.who=p.userid'),
'where' => array(
'p.login_name like "%@custis.ru"',
),
'fielddescs' => array(
'login_name' => array(
'name' => 'Сотрудник',
'group' => array(
'name' => 'Группа',
'join' => [
'ug' => [ 'INNER', 'bugs3.user_group_map', [ 'ug.user_id=t.who', 'ug.isbless=0' ] ],
'g' => [ 'INNER', 'bugs3.groups', [ 'g.id=ug.group_id' ] ],
],
'sql' => 'g.id',
'options' => function($olap)
{
return $olap->mysql()->select('bugs3.groups', 'id, name', array('isbuggroup=1'), array('ORDER BY' => 'name'));
}
),
'who' => array(
'name' => 'Логин',
'sql' => 'p.login_name',
/* 'options' => function($olap)
{
return $olap->mysql()->select('bugs3.profiles', 'userid id, login_name name', array('login_name like "%@custis.ru" and realname not like \'Группа%\''));
}*/
),
'bug_when' => array(
'name' => 'Момент',
'name' => 'Момент времени',
'le_ge' => true,
'is_time' => true,
'format' => TS_DB,
@ -93,6 +117,40 @@ OLAP::$sources = array(
'name' => 'Часы',
'le_ge' => true,
),
'bug_id' => array(
'name' => 'ID бага',
'sql' => 't.bug_id',
'le_ge' => true,
),
'product' => array(
'name' => 'Продукт',
'sql' => 'pr.name',
),
'component' => array(
'name' => 'Компонент',
'sql' => 'c.name',
),
'cf_bug_type' => array(
'name' => 'Тип бага',
'sql' => 'bt.value',
),
'da_type' => array(
'name' => 'Время ДА',
'sql' => function($olap)
{
$arch_product = $olap->mysql()->select('bugs3.products', 'id', [ 'name' => '-Arch_Other' ], NULL, MS_VALUE);
$arch_components = $olap->mysql()->select('bugs3.components', 'id', [ 'name LIKE ?' => 'arch%' ], NULL, MS_COL);
$arch_bug_types = $olap->mysql()->select('bugs3.cf_bug_type', 'id', [ 'value LIKE ?' => 'arch%' ], NULL, MS_COL);
return '(CASE'.
($arch_product ? ' WHEN b.product_id='.$arch_product.' THEN \'ДА\'' : '').
($arch_components || $arch_bug_types ? ' WHEN '.
($arch_components ? 'b.component_id IN ('.implode(',', $arch_components).')' : '').
($arch_components && $arch_bug_types ? ' OR ' : '').
($arch_bug_types ? 'b.cf_bug_type IN ('.implode(',', $arch_bug_types).')' : '').
' THEN \'Арх\'' : '').
' ELSE \'Другое\' END)';
}
),
),
),
);

View File

@ -19,7 +19,7 @@ p { margin: 4px 0; }
.themes li { padding: 0; display: inline; margin-right: 8px; }
.simpletable, .simpletable td { border: 1px solid black; }
.simpletable { border-collapse: collapse; }
.simpletable.center td { text-align: center; }
.simpletable.center td { text-align: right; }
.simpletable td ul { padding: 0 6px 0 20px; }
.simpletable td li { text-align: left; }
.simpletable th { padding: 3px 8px; background-color: #a0a0a0; vertical-align: top; }