static function prepareSelectViewElement($elem, $select, $isInitEntityAggregated, $fList, $fChainList,
$helperClassName, EntityBase $entity)
{
$selectElem = null;
$totalInfo = null;
$alias = null;
if (empty($elem['aggr']) && !mb_strlen($elem['prcnt']))
{
$selectElem = $elem['name'];
}
else
{
$expression = '';
/** @var EntityField $field */
$field = $fList[$elem['name']];
$chain = $fChainList[$elem['name']];
$sourceAlias = $alias = $chain->getAlias();
$dataType = call_user_func(array($helperClassName, 'getFieldDataType'), $field);
// Need pack 1:N aggregations into subquery?
$needPack1NAggr = false;
if ($chain->hasBackReference() && $elem['aggr'] != 'GROUP_CONCAT')
{
$confirm = call_user_func_array(
array($helperClassName, 'confirmSelectBackReferenceRewrite'),
array(&$elem, $chain)
);
if ($confirm)
{
$needPack1NAggr = true;
}
}
if (!empty($elem['aggr']))
{
$alias = $elem['aggr'] . '_' . $alias;
if ($dataType == 'boolean')
{
// sum int for boolean
global $DB;
/** @var EntityBooleanField $field */
$trueValue = $field->normalizeValue(true);
$localDef = 'CASE WHEN %s = ''.$DB->ForSql($trueValue).'' THEN 1 ELSE 0 END';
}
else
{
$localDef = '%s';
}
if ($elem['aggr'] == 'COUNT_DISTINCT')
{
$dataType = 'integer';
$expression = array(
'COUNT(DISTINCT '.$localDef.')', $elem['name']
);
}
else
{
if ($dataType == 'boolean')
{
$dataType = 'integer';
}
if ($elem['aggr'] == 'GROUP_CONCAT')
{
$expression = array(
$localDef, $elem['name']
);
}
else
{
if ($elem['aggr'] === 'AVG')
{
if (!is_array($totalInfo))
{
$totalInfo = [];
}
$totalInfo['average'] = [
'type' => 'average',
'cnt' => [
'alias' => $sourceAlias.'_AVGCNT',
'def' => [
'data_type' => 'integer',
'expression' => ['COUNT(1)']
]
],
'sum' => [
'alias' => $sourceAlias.'_AVGSUM',
'def' => [
'data_type' => $dataType,
'expression' => ['SUM('.$localDef.')', $elem['name']]
]
]
];
}
else
{
if ($elem['aggr'] === 'MIN' || $elem['aggr'] === 'MAX')
{
$typeMap = ['MIN' => 'minimum', 'MAX' => 'maximum'];
$type = $typeMap[$elem['aggr']];
if (!is_array($totalInfo))
{
$totalInfo = [];
}
$totalInfo[$type] = ['type' => $type];
unset($typeMap, $type);
}
}
$expression = [$elem['aggr'].'('.$localDef.')', $elem['name']];
}
}
// pack 1:N aggregations into subquery
if ($needPack1NAggr)
{
$filter = array();
foreach ($entity->GetPrimaryArray() as $primary)
{
$filter['='.$primary] = new CSQLWhereExpression(
'?#', ToLower($entity->getCode()).'.'.$primary
);
}
$query = new EntityQuery($entity);
$query->addSelect(new EntityExpressionField('X', $expression[0], $elem['name']));
$query->setFilter($filter);
$query->setTableAliasPostfix('_sub');
$expression = array('('.$query->getQuery().')');
// double aggregation if init entity aggregated
if ($isInitEntityAggregated)
{
if ($elem['aggr'] == 'COUNT_DISTINCT')
{
$expression[0] = 'SUM('.$expression[0].')';
}
else
{
if ($elem['aggr'] === 'AVG')
{
$cntQuery = new EntityQuery($entity);
$cntQuery->addSelect(new EntityExpressionField('CNT', 'COUNT(1)', $elem['name']));
$cntQuery->setFilter($filter);
$cntQuery->setTableAliasPostfix('_cnt');
$sumQuery = new EntityQuery($entity);
$sumQuery->addSelect(new EntityExpressionField(
'SUM', 'SUM('.$localDef.')', $elem['name'])
);
$sumQuery->setFilter($filter);
$sumQuery->setTableAliasPostfix('_sum');
if (!is_array($totalInfo))
{
$totalInfo = [];
}
$totalInfo['average'] = [
'type' => 'average',
'cnt' => [
'alias' => $sourceAlias.'_AVGCNT',
'def' => [
'data_type' => 'integer',
'expression' => ['SUM(('.$cntQuery->getQuery().'))']
]
],
'sum' => [
'alias' => $sourceAlias.'_AVGSUM',
'def' => [
'data_type' => $dataType,
'expression' => ['SUM(('.$sumQuery->getQuery().'))']
]
]
];
unset($cntQuery, $sumQuery);
}
$expression[0] = $elem['aggr'].'('.$expression[0].')';
}
}
}
}
if($elem['prcnt'] <> '')
{
$alias = $alias.'_PRCNT';
$dataType = 'integer';
if($elem['prcnt'] == 'self_column')
{
if(empty($expression))
{
$expression = array('%s', $elem['name']);
}
}
else
{
if(empty($expression))
{
$localDef = '%s';
$localMembers = array($elem['name']);
}
else
{
$localDef = $expression[0];
$localMembers = array_slice($expression, 1);
}
list($remoteAlias, $remoteSelect) = self::prepareSelectViewElement(
$select[$elem['prcnt']],
$select,
$isInitEntityAggregated,
$fList,
$fChainList,
$helperClassName,
$entity
);
if(is_array($remoteSelect) && !empty($remoteSelect['expression']))
{
// remote field is expression
$remoteDef = $remoteSelect['expression'][0];
$remoteMembers = array_slice($remoteSelect['expression'], 1);
$alias = $alias.'_FROM_'.$remoteAlias;
}
else
{
// remote field is usual field
$remoteDef = '%s';
$remoteMembers = array($remoteSelect);
$remoteAlias = EntityQueryChain::getAliasByDefinition($entity, $remoteSelect);
$alias = $alias.'_FROM_'.$remoteAlias;
}
// Expression
// 'ROUND(STATUS / ID * 100)'
// 'ROUND( (EX1(F1, F2)) / (EX2(F3, F1)) * 100)',
// F1, F2, F3, F1
$exprDef = '('.$localDef.') / ('.$remoteDef.') * 100';
$expression = array_merge(array($exprDef), $localMembers, $remoteMembers);
// Total expression
if(!is_array($totalInfo))
{
$totalInfo = [];
}
$totalInfo['prcntFromCol'] = [
'type' => 'prcntFromCol',
'local' => [
'alias' => $sourceAlias.'_PRCNTFC',
'def' => [
'data_type' => $dataType,
'expression' => array_merge(array($localDef), $localMembers)
]
],
'remote' => [
'alias' => $remoteAlias
]
];
}
}
$selectElem = array(
'data_type' => $dataType,
'expression' => $expression
);
}
return array($alias, $selectElem, $totalInfo);
}