| 
			
			 | 
		#1 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Вопрос: Существет ли какой-либо еще способ подсчитать количество строк в Query (несколько таблиц-источников), кроме тупого сканирования всех записей по while (qr.next)? 
		
		
		
		
		
		
			
		
		
		
		
	Дело в том, что это относительно медленный процесс. У меня получилось примерно 500 строк в секунду. Ответ:да, конечно, можно. SysQuery::countTotal(myQuery)  | 
| 
	
 | 
| 
			
			 | 
		#2 | 
| 
			
			 Administrator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Проблема в том, что 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;
				__________________ 
		
		
		
		
	Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me  | 
| 
	
 | 
| 
			
			 | 
		#3 | 
| 
			
			 Administrator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Вот SysQuery с методом countTotalRNR, который обобщает все вышесказанное (плюс еще немного к человеческому виду приведенный).
		 
		
		
		
			
				__________________ 
		
		
		
		
	Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me  | 
| 
	
 | 
| 
			
			 | 
		#4 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	Код: ret = record.(RecId);
while (queryRun.next()) {
   record = queryRun.getNo(1);
   ret += record.(RecId);
}
return ret;Моё предложение: Код: loops = 0;
while (queryRun.next()) 
{
   record = queryRun.getNo(1);
   ret += record.(RecId);
   loops++;
}
ret = (loops ? loops : ret);
return ret; | 
| 
	
 | 
| 
			
			 | 
		#5 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			чувствую, что вопрос еще открыт, поэтому рановато ему еще в FAQ  
		
		
		
		
		
		
			
		
		
		
		
	 .переношу эту тему в обсуждение программирования. Спасибо, Wamr  | 
| 
	
 | 
| 
			
			 | 
		#6 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Итак, насколько я понимаю, есть метод countTotal - он возвращает количество записей в запросе. и есть countLoops - он возвращает количество группировок. 
		
		
		
		
		
		
			
		
		
		
		
	Насколько я понял Максима, countTotal дает направильные результаты когда в query прилинковано несколько таблиц. Так?  | 
| 
	
 | 
| 
			
			 | 
		#7 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			например, в у меня стандартном демопримере 
		
		
		
		
		
		
			
		
		
		
		
	Код: static void Job10(Args _args)
{
    QueryRun q = new QueryRun(querystr(LedgerTransAll));
;
    info(strfmt('%1',SysQuery::countTotal(q)));
}нормально работает и для запроса LedgerTrans, хотя там группировки. А вот для querystr(LedgerTable) показывает чушь, поскольку там dinalink. В этом проблема? Maxim, согласен, что код в webTableLookup.run() выглядит более правильным. Может сделаешь проект, в котором будет исправленный код для SysQuery с учетом замечаний wamr? Чтобы считался и loops тоже. Спасибо за качественный совет. И спасибо за webTableLookup.run()  | 
| 
	
 | 
| 
			
			 | 
		#8 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Можно несколько глупых вопросов? Я еще очень плохо ориентируюсь в Axapta вообще и где что искать в частности. 
		
		
		
		
		
		
		
	-) О какой версии идет речь? У меня 2.5 и класса webTableLookup я не нашел. Или где его искать? -) В примере исправленного кода SysQuery выложенного Максимом есть строка Код: countQuery = SysQuery::copyDynalinks(countQuery, _query); -) dinalink - это что собственно такое? Еще один совсем глупый вопрос: В коде Максима предельное значение счетчика вычисляется непосредственно в заголовке цикла Код: for (k = 2; k <= countQuery.dataSourceCount();k++)  | 
| 
	
 | 
| 
			
			 | 
		#9 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Господа модераторы, убейте, пожалуйста 2 из 3 повторяющих сообщений (loops++), а заодно и это. 
		
		
		
		
		
		
		
	К тему вернусь сегодня попозже.  | 
| 
	
 | 
| 
			
			 | 
		#10 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от Владимир Максимов
			
			 
-) О какой версии идет речь? У меня 2.5 и класса webTableLookup я не нашел. Или где его искать? 
		
	-) В примере исправленного кода SysQuery выложенного Максимом есть строка Код: countQuery = SysQuery::copyDynalinks(countQuery, _query); -) dinalink - это что собственно такое? Еще один совсем глупый вопрос: В коде Максима предельное значение счетчика вычисляется непосредственно в заголовке цикла Код: for (k = 2; k <= countQuery.dataSourceCount();k++) В 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 - будет вычисляться. Эксперимент показывает, что вычисляется каждый раз.  | 
| 
	
 | 
| 
			
			 | 
		#11 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Большое спасибо.  
		
		
		
		
		
		
		
	Однако вопрос по 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);
}Код: Query countQuery = _query.newObject(_query.pack(TRUE)); Если тем не менее это необходимо, то есть ли в этом необходимость в версии 2.5? Если есть, то как это сделать вручную (поскольку нет метода SysQuery::copyDynalinks() ) Извиняюсь за такую навязчивость, но при такой слабой документированности Axapta я по пол-дня соображаю что же именно и каким образом делает та или иная команда  
		 | 
| 
	
 | 
| 
			
			 | 
		#12 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			при программном создании query связи автоматически не создаются. 
		
		
		
		
		
		
			
		
		
		
		
	в отчетах и формах надо указать галочку, что автоматически создавать связи можно, тогда для отчетов и форм, Аксапта создаст связь автоматом. Если объекты создаются из AOT, то там эту галочку разработчик должен указать в свойствах. Почему dinalink копируется, а не пересоздается? Потому что в исходном запросе динасвязи могли быть подредактированы программистом.  
		 | 
| 
	
 | 
| 
			
			 | 
		#13 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			В данном случае речь идет не о создании query с нуля, а о создании query как копии существующего. Для чего и используется _query.pack(). 
		
		
		
		
		
		
		
	Но ведь, если я правильно понимаю, _query.pack(TRUE) как раз и должен передать все настройки сделанные в query. В том числе и изменения внесенные в связи как самой Axapta, так и пользователем. Или это не так?  | 
| 
	
 | 
| 
			
			 | 
		#14 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			pack нужен не для того, чтобы скопировать все, а для того, чтобы передать информацию с клиента на сервер и обратно. 
		
		
		
		
		
		
			
		
		
		
		
	см. http://technet.navision.com/usered/BPH/Bes.../PackUnpack.htm Что конкретно делает pack зависит от реализации класса. Поэтому надо проверить, передаются ли dinalink в pack'е. Я наверняка не знаю.  | 
| 
	
 | 
| 
			
			 | 
		#15 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			В виде исключения, описание Query.Pack() есть в АОТ. Оказывается он просто не пакует DynaLinks, а параметр всего лишь влияет на то выдавать сообщение об ошибке в случае наличия DynaLinks или нет. 
		
		
		
		
		
		
		
	В 2.5 если необходимо паковать DynaLinks советуют их явно прописывать в DataSource Т.е. изменения Максима для 2.5 получается неприменимы? Или возможны варианты?  | 
| 
	
 | 
| 
			
			 | 
		#16 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			надо Максима дождаться. Он сейчас не в офисе.
		 
		
		
		
		
		
		
			
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#17 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Хочу исправить свою ошибку: 
		
		
		
		
		
		
		
	Код: 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. Не представляю себе, как можно корректно упаковать динамическую связь одного объекта (курсора) с другим объектом (запрос)? А как потом распаковать?  | 
| 
	
 | 
| 
			
			 | 
		#18 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от Wamr
			
			 
Уточню, что под количество строк запроса я понимаю кол-во строк получаемых в результате запроса после всех фильтраций и агрегаций. 
		
	countLoops и должен возвращать число группировок, а countTotal должен возвращать БЫСТРО число строк в таблице.  | 
| 
	
 | 
| 
			
			 | 
		#19 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от mazzy
			
			 
countLoops и должен возвращать число группировок, 
		
	в стандартном countPrim.  | 
| 
	
 | 
| 
			
			 | 
		#20 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			ооо. ну ни фига себе тема... 
		
		
		
		
		
		
			
		
		
		
		
	не, метод Максима тоже не пойдет, поскольку выборка делается там, где ее вызвали. Если вызвали на клиенте, то и запрос выполняться будет на клиенте... А это трафик по тонкому каналу...  | 
| 
	
 |