|
|
#21 |
|
Участник
|
итак, предлагаю код метода SysQuery::countPrim для 3.0
Код: private server static container countPrim(container _queryPack)
{
...
;
countQueryRun = new QueryRun(_queryPack);
countQuery = countQueryRun.query();
for (k = 1; k <= countQuery.dataSourceCount();k++)
{
qbds = countQuery.dataSourceNo(k);
qbds.update(false);
//qbds.sortClear(); // Вот этот метод сильно мешал!
qbfl = qbds.fields();
qbfl.dynamic(false);
qbfl.clearFieldList();
qbfl.addField(FieldNum(Common,recId),SelectionField::COUNT);
}
countQueryRun = new QueryRun(countQuery);
while (countQueryRun.next())
{
common = countQueryRun.getNo(1);
counter += common.recId;
loops++;
}
return [counter,((loops > 1)? loops : counter)];
} |
|
|
|
|
#22 |
|
Участник
|
код метода SysQuery::countPrim для 2.5
Код: server static container countPrim(QueryRun _queryRun)
{
...
con = _queryRun.pack();
countQueryRun = new QueryRun(con);
countQuery = countQueryRun.query();
for (k = 1; k <= countQuery.dataSourceCount();k++)
{
qbds = countQuery.dataSourceNo(k);
qbds.update(false);
//qbds.sortClear(); // Мешал вот этот метод!
qbfl = qbds.fields();
qbfl.dynamic(false);
qbfl.clearFieldList();
qbfl.addField(FieldNum(Common,recId),SelectionField::COUNT);
}
countQueryRun = new QueryRun(countQuery);
while (countQueryRun.next())
{
common = countQueryRun.getNo(1);
counter += common.recId;
loops++;
}
return [counter,((loops > 1)? loops : counter)];
} |
|
|
|
|
#23 |
|
Участник
|
проверочный job. подходит для обеих версий
Код: static void testSysQuery_CountLoops_rnr(Args _args)
{
Query q = new Query();
QueryRun qr;
QueryBuildDataSource qbds;
QueryBuildDataSource qbds2;
LedgerTable lt;
LedgerTrans ltrans;
Integer loops;
Integer Total;
qbds = q.addDataSource(tablenum(LedgerTable));
qbds.addSortField(fieldnum(LedgerTable,AccountPlType));
qbds.orderMode(0);
qbds2 = qbds.addDataSource(tablenum(LedgerTrans));
qbds2.joinMode(JoinMode::INNERJOIN);
qbds2.addLink(fieldnum(LedgerTable,AccountNum),fieldnum(LedgerTrans,AccountNum));
qbds2.addSortField(fieldnum(LedgerTrans,TransDate));
qbds2.orderMode(0);
info(q.dataSourceNo(1).toString());
qr = new QueryRun(q);
info(strfmt('Total: %1',SysQuery::countTotal(qr)));
info(strfmt('Loops: %1',SysQuery::countLoops(qr)));
} |
|
|
|
|
#24 |
|
Участник
|
посмотрите, поиграйтесь orderMode(0) или orderMode(1) для обеих таблиц.
Обратите внимание, какие параметры и когда передаются между клиентом и сервером. Обратите внимание, как соптимизировали трафик в 3.0. Что мешало в старой версии? В старой версии жутко мешал qbds.sortClear(). В целом был взят метод Максима. Единственно, что было исправлено в его методе, ставим Count(RecID) не только в первой таблице, но и во всех остальных. Что получаем? countTotal всегда достаточно быстро возвращает ОБЩЕЕ количество ЗАПИСЕЙ. countLoops всегда достаточно быстро возвращает количество ГРУППИРОВОК. интересно поведение countLoops, когда начинаете играться с OrderMode в проверочном примере. (для того, чтобы получить полную картину, раскоментарьте метод info в CountPrim) Так, если оба OrderMode = 0, то CountLoop = 4110. Правильно все количество записей, вычисляется на сервере, сама Аксапта получает управление только один раз. Если OrderMode = 1,0, то CountLoop = 5. Это количетсво группировок по типам счетов. Все правильно. У меня есть проводки по всем типам счетов, кроме загловков, итогов. Если OrderMode = 0,1, то CountLoop = 116. Это количество различных дат в таблице финансовых проводок. Если же OrderMode = 1,1, то CountLoop = 272. Это количество дат внутри каждого типа счета. Т.е. можно теперь можно делать следующее (причем progress bar будет работать правильно для любого запроса!) Код: SysOperationProgress progress = new SysOperationProgress();
progress.setTotal(SysQuery::countLoops(qr));
while( qr.next() ){
// ...do somthing...
progress.incCount();
}wamr, я правильно понял идею насчет loops? |
|
|
|
|
#25 |
|
Участник
|
Цитата:
progress bar будет работать правильно для любого запроса!
|
|
|
|
|
#26 |
|
Участник
|
также должно работать.
ближе к вечеру проверю. |
|
|
|
|
#27 |
|
Участник
|
в целом модификация работает правильно.
Бывают глюки на бессмысленные запросы. Например, если сделать NoExistsjoin с группировкой по подчиненной таблице... В нормальных случаях работает корректно. Если сомневаетесь в работе, то используйте try/catch для обрамления вызова. Вопрос помещен в FAQ Как подсчитать количество записей, возвращаемых Query Спасибо участникам обсуждения |
|
|
|
|
#28 |
|
Участник
|
Цитата:
Сообщение от mazzy
итак, предлагаю код метода SysQuery::countPrim для 3.0
Код: private server static container countPrim(container _queryPack)
{
...
;
countQueryRun = new QueryRun(_queryPack);
countQuery = countQueryRun.query();
for (k = 1; k <= countQuery.dataSourceCount();k++)
{
qbds = countQuery.dataSourceNo(k);
qbds.update(false);
qbfl = qbds.fields();
qbfl.dynamic(false);
qbfl.clearFieldList();
qbfl.addField(FieldNum(Common,recId),SelectionField::COUNT);
}
...
}Цитата:
Сообщение от Maxim Gorbunov
Более правильный метод подсчета записей, возвращаемых Query см. в методе webTableLookup.run() Там есть вложенный метод computeRecordCount, который все и делает. Вкратце, суть метода такова. Сначала создается копия исходного Query. Для всех DataSource в Query отменяется динамическое создание списка выбираемых полей и добавляется только поле TableId (чтобы хоть что-то выбиралось). Далее, в самый главный DataSource добавляется Selection Field RecId с функцией агрегации COUNT
Код: for (k = 1; k <= countQuery.dataSourceCount();k++)
{
qbds = countQuery.dataSourceNo(k);
qbds.update(false);
qbfl = qbds.fields();
qbfl.dynamic(false);
qbfl.clearFieldList();
if (k == 1)
qbfl.addField(fieldnum(Common, RecId), SelectionField::Count);
else
qbfl.addField(fieldnum(Common, TableId));
} |
|
|
|
|
#29 |
|
Участник
|
дальнейшее развитие и исправления здесь
http://axforum.info/forums/showthrea...047#post258047 |
|
|