AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 20.01.2004, 13:43   #1  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Вопрос: Существет ли какой-либо еще способ подсчитать количество строк в Query (несколько таблиц-источников), кроме тупого сканирования всех записей по while (qr.next)?

Дело в том, что это относительно медленный процесс. У меня получилось примерно 500 строк в секунду.

Ответ:да, конечно, можно.

SysQuery::countTotal(myQuery)
__________________
полезное на axForum, github, vk, coub.
Старый 20.01.2004, 14:43   #2  
Maxim Gorbunov is offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2,483 / 645 (26) +++++++
Регистрация: 27.11.2001
Адрес: Dubai, UAE
Проблема в том, что SysQuery::countTotal правильно работает только в случае, если в Query один DataSource.

Более правильный метод подсчета записей, возвращаемых Query см. в методе webTableLookup.run() Там есть вложенный метод computeRecordCount, который все и делает.

Вкратце, суть метода такова. Сначала создается копия исходного Query. Для всех DataSource в Query отменяется динамическое создание списка выбираемых полей и добавляется только поле TableId (чтобы хоть что-то выбиралось). Далее, в самый главный DataSource добавляется Selection Field RecId с функцией агрегации COUNT (если по простому, делается SELECT COUNT(RecId)). Созданный Query запускается и получает результат.

В большинстве случаев, результат верный. Однако, если в исходном используется GroupBy, функция вернет количество записей только в первой группе. Для исправления ситуации нужен небольшой bug fix. Во-первых, добавьте в функцию локальную переменную ret типа int. Во-вторых, вместо
Код:
return record.(recId);
вставьте
Код:
ret = record.(RecId);
while (queryRun.next()) {
    record = queryRun.getNo(1);
    ret += record.(RecId);
}
return ret;
После этого функция становится вполне работоспособной и ее можно добавить к классу SysQuery с целью дальнейшего ее использования.
__________________
Not registered yet? Register here!
Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me
Старый 20.01.2004, 15:12   #3  
Maxim Gorbunov is offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2,483 / 645 (26) +++++++
Регистрация: 27.11.2001
Адрес: Dubai, UAE
Вот SysQuery с методом countTotalRNR, который обобщает все вышесказанное (плюс еще немного к человеческому виду приведенный).
Вложения
Тип файла: xpo SysQuery.xpo (1.9 Кб, 230 просмотров)
__________________
Not registered yet? Register here!
Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me
Старый 20.01.2004, 15:42   #4  
Wamr_imported is offline
Wamr_imported
Участник
 
101 / 10 (1) +
Регистрация: 08.01.2004
Цитата:
Код:
ret = record.(RecId);
while (queryRun.next()) {
   record = queryRun.getNo(1);
   ret += record.(RecId);
}
return ret;
И где тут, простите, countLoops?

Моё предложение:
Код:
loops = 0;
while (queryRun.next()) 
{
   record = queryRun.getNo(1);
   ret += record.(RecId);
   loops++;
}
ret = (loops ? loops : ret);
return ret;
Старый 20.01.2004, 19:44   #5  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
чувствую, что вопрос еще открыт, поэтому рановато ему еще в FAQ .
переношу эту тему в обсуждение программирования.

Спасибо, Wamr
__________________
полезное на axForum, github, vk, coub.
Старый 20.01.2004, 20:17   #6  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Итак, насколько я понимаю, есть метод countTotal - он возвращает количество записей в запросе. и есть countLoops - он возвращает количество группировок.

Насколько я понял Максима, countTotal дает направильные результаты когда в query прилинковано несколько таблиц. Так?
__________________
полезное на axForum, github, vk, coub.
Старый 20.01.2004, 20:35   #7  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
например, в у меня стандартном демопримере
Код:
static void Job10(Args _args)
{
    QueryRun q = new QueryRun(querystr(LedgerTransAll));
;
    info(strfmt('%1',SysQuery::countTotal(q)));
}
сообщает, что проводок 4110

нормально работает и для запроса LedgerTrans, хотя там группировки. А вот для querystr(LedgerTable) показывает чушь, поскольку там dinalink. В этом проблема?

Maxim, согласен, что код в webTableLookup.run() выглядит более правильным. Может сделаешь проект, в котором будет исправленный код для SysQuery с учетом замечаний wamr? Чтобы считался и loops тоже.

Спасибо за качественный совет. И спасибо за webTableLookup.run()
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 11:03   #8  
Владимир Максимов_imported is offline
Владимир Максимов_imported
Участник
 
33 / 10 (1) +
Регистрация: 20.01.2004
Можно несколько глупых вопросов? Я еще очень плохо ориентируюсь в Axapta вообще и где что искать в частности.

-) О какой версии идет речь? У меня 2.5 и класса webTableLookup я не нашел. Или где его искать?

-) В примере исправленного кода SysQuery выложенного Максимом есть строка

Код:
countQuery = SysQuery::copyDynalinks(countQuery, _query);
Что собственно делает этот метод, поскольку у меня в 2.5 я его не обнаружил.

-) dinalink - это что собственно такое?

Еще один совсем глупый вопрос:

В коде Максима предельное значение счетчика вычисляется непосредственно в заголовке цикла

Код:
for (k = 2; k <= countQuery.dataSourceCount();k++)
Вопрос в том, вычисляется ли максимальное значение k при каждом шаге цикла или один раз при инициализации цикла? Т.е. будет ли выполнен расчет countQuery.dataSourceCount(); один раз или столько раз сколько шагов в цикле?
Старый 21.01.2004, 11:11   #9  
Wamr_imported is offline
Wamr_imported
Участник
 
101 / 10 (1) +
Регистрация: 08.01.2004
Господа модераторы, убейте, пожалуйста 2 из 3 повторяющих сообщений (loops++), а заодно и это.
К тему вернусь сегодня попозже.
Старый 21.01.2004, 13:31   #10  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Владимир Максимов
-) О какой версии идет речь? У меня 2.5 и класса webTableLookup я не нашел. Или где его искать?

-) В примере исправленного кода SysQuery выложенного Максимом есть строка

Код:
countQuery = SysQuery::copyDynalinks(countQuery, _query);
Что собственно делает этот метод, поскольку у меня в 2.5 я его не обнаружил.

-) dinalink - это что собственно такое?

Еще один совсем глупый вопрос:

В коде Максима предельное значение счетчика вычисляется непосредственно в заголовке цикла

Код:
for (k = 2; k <= countQuery.dataSourceCount();k++)
Вопрос в том, вычисляется ли максимальное значение k при каждом шаге цикла или один раз при инициализации цикла? Т.е. будет ли выполнен расчет countQuery.dataSourceCount(); один раз или столько раз сколько шагов в цикле?
здесь говорилось о 3.0.

В 2.5 действительно нет класса webTableLookup. Поскольку корпоративный портал для 3.0 сильно доработали.

SysQuery::copyDynalinks также присутствует только в 3.0. Этот метод копирует связи (relation) между таблицами. Причем связи, установленные Аксаптой автоматически.

См. руководство разработчика, ключевые слова "auto-define relations", "table relations", "Creating a relationship on an Extended Data Type".

Это есть и в 2.5, и в 3.0.
Руководство разработчика для 3.0 можно взять и здесь http://technet.navision.com/usered/Axapta3...v02.00-ENUS.zip

Насчет вычислений. Нигде не видел описания поведения в таких случаях специально для Аксапты. Подозреваю, что и в этом случае будут действовать правила из Java - будет вычисляться.

Эксперимент показывает, что вычисляется каждый раз.
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 14:57   #11  
Владимир Максимов_imported is offline
Владимир Максимов_imported
Участник
 
33 / 10 (1) +
Регистрация: 20.01.2004
Большое спасибо.

Однако вопрос по DynaLink нуждается в уточненнии.

В коде Максима (исправление SysQuery) создание копии Query осуществляется следующим образом:

Код:
public client server static Integer countTotalRNR(Query _query)
{
    Query       countQuery = _query.newObject(_query.pack(FALSE));

    // Add contribution from dynalinks...
    countQuery = SysQuery::copyDynalinks(countQuery, _query);
}
К чему такие сложности? Разве связи созданные автоматически самой Axapta не должны также автоматически создаваться во всех случаях? Т.е. почему нельзя было обойтись стандартным

Код:
Query       countQuery = _query.newObject(_query.pack(TRUE));
В чем смысл принудительной установки связей, которые теоретически должны быть установлены автоматически?

Если тем не менее это необходимо, то есть ли в этом необходимость в версии 2.5? Если есть, то как это сделать вручную (поскольку нет метода SysQuery::copyDynalinks() )

Извиняюсь за такую навязчивость, но при такой слабой документированности Axapta я по пол-дня соображаю что же именно и каким образом делает та или иная команда
Старый 21.01.2004, 15:24   #12  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
при программном создании query связи автоматически не создаются.

в отчетах и формах надо указать галочку, что автоматически создавать связи можно, тогда для отчетов и форм, Аксапта создаст связь автоматом. Если объекты создаются из AOT, то там эту галочку разработчик должен указать в свойствах.

Почему dinalink копируется, а не пересоздается?
Потому что в исходном запросе динасвязи могли быть подредактированы программистом.
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 15:34   #13  
Владимир Максимов_imported is offline
Владимир Максимов_imported
Участник
 
33 / 10 (1) +
Регистрация: 20.01.2004
В данном случае речь идет не о создании query с нуля, а о создании query как копии существующего. Для чего и используется _query.pack().

Но ведь, если я правильно понимаю, _query.pack(TRUE) как раз и должен передать все настройки сделанные в query. В том числе и изменения внесенные в связи как самой Axapta, так и пользователем. Или это не так?
Старый 21.01.2004, 15:45   #14  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
pack нужен не для того, чтобы скопировать все, а для того, чтобы передать информацию с клиента на сервер и обратно.
см. http://technet.navision.com/usered/BPH/Bes.../PackUnpack.htm

Что конкретно делает pack зависит от реализации класса.
Поэтому надо проверить, передаются ли dinalink в pack'е.
Я наверняка не знаю.
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 17:43   #15  
Владимир Максимов_imported is offline
Владимир Максимов_imported
Участник
 
33 / 10 (1) +
Регистрация: 20.01.2004
В виде исключения, описание Query.Pack() есть в АОТ. Оказывается он просто не пакует DynaLinks, а параметр всего лишь влияет на то выдавать сообщение об ошибке в случае наличия DynaLinks или нет.

В 2.5 если необходимо паковать DynaLinks советуют их явно прописывать в DataSource

Т.е. изменения Максима для 2.5 получается неприменимы? Или возможны варианты?
Старый 21.01.2004, 17:51   #16  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
надо Максима дождаться. Он сейчас не в офисе.
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 18:52   #17  
Wamr_imported is offline
Wamr_imported
Участник
 
101 / 10 (1) +
Регистрация: 08.01.2004
Хочу исправить свою ошибку:
Код:
loops = 0;
while (queryRun.next()) 
{
  record = queryRun.getNo(1);
  ret += record.(RecId);
  loops++;
}
ret = (loops>1 ? loops : ret);
return ret;
Уточню, что под количество строк запроса я понимаю кол-во строк получаемых в результате запроса после всех фильтраций и агрегаций.

С задачей подсчета строк в запросе я сталкивался в 2х случаях:
- когда требовалось выводить какие-то агрегированные значения в форме с учетом фильтров пользователя и dynalink-ов c другими формами;
- для инициализация прогресса перед выполнением какого-то длительного процесса.
И в том, и в другом случаи важен не только результат, но и скорость. Т.е. простой перебор строк (читай countTotal) не подходит.
При наличии GROUP BY даже метод Максима приходит к перебору.
Простого способа посчитать строки с группировками НЕТ. Т.е. для таких вычислений надо искать какой-то обходной путь.

Если честно, то я почти никогда не использовал универсальный метод подсчета кол-ва строк в запросе, так как всегда старался сделать несколько вычислений (кол-ва, суммы..) за один проход
-----------------------

Паковать dynalink.
Не представляю себе, как можно корректно упаковать динамическую связь одного объекта (курсора) с другим объектом (запрос)? А как потом распаковать?
Старый 21.01.2004, 19:36   #18  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Wamr
Уточню, что под количество строк запроса я понимаю кол-во строк получаемых в результате запроса после всех фильтраций и агрегаций.
может я чего не понял, то насколько я понимаю,
countLoops и должен возвращать число группировок,
а countTotal должен возвращать БЫСТРО число строк в таблице.
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 20:07   #19  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от mazzy
countLoops и должен возвращать число группировок,
ни фига! обратите внимание на qbds.sortClear();
в стандартном countPrim.
__________________
полезное на axForum, github, vk, coub.
Старый 21.01.2004, 20:39   #20  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
ооо. ну ни фига себе тема...

не, метод Максима тоже не пойдет, поскольку выборка делается там, где ее вызвали. Если вызвали на клиенте, то и запрос выполняться будет на клиенте... А это трафик по тонкому каналу...
__________________
полезное на axForum, github, vk, coub.
 


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 23:15.