21.05.2022, 01:30 | #1 |
Участник
|
Вложенный запрос (DAX2012)
Добрый день!
Продолжая эпопею с оптимизацией запросов, появилась потребность в получении значения не перебором, а единым запросом. Необходимо сделать следующее: 1) сгруппировать таблицу по 2 полям 2) посчитать максимальное значение по полю 2, сгруппировав по полю 1 К сожалению на текущий момент в окружении нет квалифицированных специалистов, приходится делать своими силами, которые крайне ограничены по знаниям, как и время на реализацию Возможно ли сделать подобный запрос в Аксапте? |
|
21.05.2022, 07:35 | #2 |
Участник
|
да, чёрным запросом
https://github.com/mazzy-ax/SysResultSet дополнительно поприсваивайте fieldnum и tablenum в какой-нибудь неиспользуемый контейнер в этом методе. тогда перекрестные ссылки покажут, что указанные поля и таблицы в этом методе используются. но вопрос скорее надо ставить не "возможно ли?", а "какое решение экономически целесообразно"? с точки зрения поддержки, с точки зрения модифицируемости и дальнейшего развития системы. например, стопудов ваши два пункта не последние, а часть какого-то большого алгоритма. в этом большом алгоритме наверняка определяются и входящие условия, и как будут использоваться результаты этого запроса. стопудов выяснится, что в алгоритме используется еще и "поле 3", "поле 4" и "поле N", из-за которых вам придется делать дополнительные выборки. |
|
|
За это сообщение автора поблагодарили: Raven Melancholic (5). |
21.05.2022, 12:06 | #3 |
Moderator
|
В DAX2012 (и даже в Dax2009) можно создать view.
Сначала создаем View с двумя полями, основанный на Query, в котором по этим двум полям группировка. Потом пишем запрос X++: while select maxof(field2),Field1 From MyView Group by field1 { } |
|
|
За это сообщение автора поблагодарили: mazzy (5), DesparioN (1). |
21.05.2022, 16:24 | #4 |
Administrator
|
Небольшие 5 копеек.
Если табличка большая по объёму (несколько миллионов записей), то будет критично, если по полям, перечисленным в условиях отбора (WHERE), условиях группировки (GROUP BY) и условиях сортировки (ORDER BY) нету хотя бы частично покрывающего (по полям, содержащие наиболее уникальные значения, можно не по всем полям) индекса. Поэтому в идеале - все типы запросов к таблице нужно свести к ограниченному количеству и по ним построить рекомендуемые базой данных индексы. Собственно поэтому количество полей в GROUP BY лучше зафиксировать и не расширять (т.е. если потребуется расширение - решать эту задачу не одним запросом, а несколькими) Совет актуален в первую очередь для периодической выборки.
__________________
Возможно сделать все. Вопрос времени |
|
23.05.2022, 08:46 | #5 |
Участник
|
Добрый день. Для меня немного непонятно, почему нельзя опустить пункт 1?
Зачем сначала делать группировку по 2 полям, чтобы потом получить максимальное с группировкой - и всё это на базе тех же самых 2 полей? Есть какой-то скрытый смысл?
__________________
// no comments |
|
|
За это сообщение автора поблагодарили: ice (1). |
23.05.2022, 09:29 | #6 |
Участник
|
Да, будет разное количество. Условно на каждую пару полей приходится по 20-30 строк. Т.е. без второго пункта будет не 2 записи, 40-60.
|
|
23.05.2022, 09:30 | #7 |
Участник
|
А я ведь главное сделал сразу вьюху, но так увлекся изучением программируемых полей, что забыл, что там можно группировать. Благодарю
|
|
23.05.2022, 09:57 | #8 |
Участник
|
как всегда в программистских задачах: помните, что группировка по полю без индекса - это Table scan. т.е. вам нужно подумать не как запрограммировать в Аксапте универсальный запрос. а о том, как сделать ваш код в целом быстрым и эффективным. возможно, стоит даже не ограничиться только SQL, а по-другому распределить нагрузку между SQL и AOS. уверяю вас, "универсальные запросы по произвольным полям" - это зло. лучше переделайте вашу схему данных. Последний раз редактировалось mazzy; 23.05.2022 в 10:02. |
|
|
За это сообщение автора поблагодарили: sukhanchik (4). |
23.05.2022, 14:23 | #9 |
Участник
|
Цитата:
Или может быть я вас не совсем так понял? Давайте разберем пример. Допустим, вы хотите узнать время последней активности по всем клиентам и группируете CustTrans по полям AccountNum(1) и TransDate(2). Пункт 1. Вы делаете группировку по AccountNum, TransDate Пункт 2. Вы также делаете группировку по AccountNum, а по TransDate ищете максимальную дату. Разве изменится что-то, если вы выкинете пункт 1 и оставите пункт 2?
__________________
// no comments |
|
23.05.2022, 16:01 | #10 |
Участник
|
Условие другое: требуется найти не максимальную дату, а максимальное количество разных дат.
|
|
|
За это сообщение автора поблагодарили: dech (1). |
23.05.2022, 23:50 | #11 |
Участник
|
Еще помучаю, если можно. Написал запрос.
В итоге, если: 1) взять COUNT(Field) order by Field DESC, то получается 2. 2) Если перебором, то получается 3 3) если в п.1 добавить фильтр по номенклатуре e которой реально 3, то получается 3. С чем это может быть связано? Для справки, если это может быть важно, Field - string |
|
24.05.2022, 07:30 | #12 |
Moderator
|
Цитата:
В таком случае, задача решается так: 1. Создается view1 по основной таблице, во вьюшке оба поля, по обоим полям стоит группировка. 2. Создается view2. View2 построено по view1, сделана группировка по ключевому полю (field1), поставлена функция count(recid) (второе поле тут строго говоря вообще не при делах, сount нужно делать по любому int64 полю, recId -наиболее очевидный кандидат). Во view2 в итоге будут находится записи в которых для каждого значения ключевого поля во втором поле будет находится число уникальных значений транзакционного поля в оригинальной таблице. |
|
24.05.2022, 08:53 | #13 |
Участник
|
Цитата:
Сообщение от DesparioN
Еще помучаю, если можно. Написал запрос.
В итоге, если: 1) взять COUNT(Field) order by Field DESC, то получается 2. 2) Если перебором, то получается 3 3) если в п.1 добавить фильтр по номенклатуре e которой реально 3, то получается 3. С чем это может быть связано? Для справки, если это может быть важно, Field - string Возможно стоит попробовать выполнение запроса на чистом SQL, без создания дополнительных вьюшек. В этом случае можно воспользоваться ORDER BY N, где N - это номер поля, участвующего в выборке. Note! Класс с вашим запросом должен исполняться на сервере.
__________________
// no comments |
|
24.05.2022, 08:54 | #14 |
Участник
|
Вы наверное ожидаете что order by будет применён к результату агрегирующей функции? В Аксапте оно так не работает. Только если, как вам уже советовали, явно зафиксировать результат агрегации в виде View, а потом уже внешним по отношению к View запросом отсортировать результат
|
|
24.05.2022, 10:12 | #15 |
Участник
|
Понял, принял. Благодарю.
|
|
24.05.2022, 18:17 | #16 |
Участник
|
Странно, что решение "в лоб" не рассматривается
1. Выборка с группировкой во временную таблицу 2. Выборка по временной таблице из п.1 View - это большие "накладные расходы" на сопровождение. Иногда нужно, конечно, но лучше обойтись
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
24.05.2022, 19:34 | #17 |
Участник
|
так задал вопрос топикстартер:
|
|
24.05.2022, 20:57 | #18 |
Участник
|
Так это решение и есть. Не перебором. Отличие только в том, что не один запрос, а два
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|