21.01.2004, 20:51 | #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)]; } |
|
21.01.2004, 20:52 | #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)]; } |
|
21.01.2004, 20:53 | #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))); } |
|
21.01.2004, 21:05 | #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? |
|
22.01.2004, 13:11 | #25 |
Участник
|
Цитата:
progress bar будет работать правильно для любого запроса!
|
|
22.01.2004, 13:19 | #26 |
Участник
|
также должно работать.
ближе к вечеру проверю. |
|
26.01.2004, 00:44 | #27 |
Участник
|
в целом модификация работает правильно.
Бывают глюки на бессмысленные запросы. Например, если сделать NoExistsjoin с группировкой по подчиненной таблице... В нормальных случаях работает корректно. Если сомневаетесь в работе, то используйте try/catch для обрамления вызова. Вопрос помещен в FAQ Как подсчитать количество записей, возвращаемых Query Спасибо участникам обсуждения |
|
06.05.2008, 18:49 | #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)); } |
|
20.09.2011, 15:35 | #29 |
Участник
|
дальнейшее развитие и исправления здесь
http://axforum.info/forums/showthrea...047#post258047 |
|