30.03.2016, 17:43 | #1 |
Участник
|
Работа с Query.
Добрый день.
Я только начинаю тесно работать с MS DynamicsAX, просьба помочь разобраться с одним вопросом. Есть диалог, с кнопкой "Выбрать", внутри должно быть 2 поля. Но проблема в том, что при данном коде отображается только одно из полей, в зависимости от того, какой queryRun возвращается. Объявил 2 QueryRun'а: X++: class ... extends RunBase { ... QueryRun queryrun1, queryrun2; ... } X++: void initQuery() { query query1 = new query(); query query2 = new query(); QueryBuildDataSource qbds1, qbds2; ; qbds1= query1.addDataSource(tableNum(Table1)); qbds2= query2.addDataSource(tablenum(Table2)); queryrun1 = new queryRun(query1); queryrun2 = new queryRun(query2); } X++: void printSheet1() { ... EDT edt1, edt2; Table1 table1; Table2 table2; ... ; while (queryrun1.next()) { table1 = queryrun1.get(tablenum(Table1)); edt1 = Table1.Field1; while (queryrun2.next()) { table2 = queryrun2.get(tableNum(Table2)); edt2 = Table2.Field2; .... } queryrun2.reset(); } queryrun1.reset(); } Если возвращаем queryrun1, то но форме будет только поле с Table1. И, соответственно, перебор будет по указанным значениям из Table1 и всем значениям из Table2. И наоборот. X++: public QueryRun queryRun() { return queryrun1; //return queryrun2; } |
|
30.03.2016, 17:57 | #2 |
Участник
|
А включить Table1 и Table2 в один Query нельзя?
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: Alucardkds (1). |
30.03.2016, 18:19 | #3 |
Участник
|
Можно, только я тогда никак не могу сообразить, каким образом организовать метод PrintSheet с перебором 2-мя while'ами.
Если я делал подобным образом, через один query, то у меня получалось, что если я беру одно значение из Table1 и несколько значений из Table2, то всё хорошо обрабатывается. А обратная ситуация - на выходе получаются не совсем корректный данные. Просто приведённый выше код работает, как ни странно, осталось только вывести на форму диалога второе поле. Последний раз редактировалось Alucardkds; 30.03.2016 в 18:31. |
|
30.03.2016, 18:52 | #4 |
Участник
|
Цитата:
Сообщение от Alucardkds
Далее есть метод, где данные обрабатываются и выводятся в ёксель:
X++: void printSheet1() { ... EDT edt1, edt2; Table1 table1; Table2 table2; ... ; while (queryrun1.next()) { table1 = queryrun1.get(tablenum(Table1)); edt1 = Table1.Field1; while (queryrun2.next()) { table2 = queryrun2.get(tableNum(Table2)); edt2 = Table2.Field2; .... } queryrun2.reset(); } queryrun1.reset(); } Вы точно этого хотите получить в результате? если да, то попробуйте выкрутиться при помощи двух последовательных queryRun.prompt() но почему-то мне кажется, что вам нужно пересмотреть постановку задачи. |
|
|
За это сообщение автора поблагодарили: Alucardkds (1). |
30.03.2016, 18:56 | #5 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: Alucardkds (1). |
31.03.2016, 09:33 | #6 |
Участник
|
Доброе утро.
Вариант с queryRun.prompt() помог решить проблему. Корректно отдельно заполняются оба query. Цитата:
Напишите что вы хотите реализовать на том языке, который вам удобен.
Или напишите SQL-запрос, который вы хотите реализовать в Аксапте. Есть отчёт, где входящими значениями являются: 1. Начальная дата. 2. Конечная дата. 3. Подразделение работников. (Данные из Table1, что представляет из себя справочник подразделений специализированных рабочих). 4. Рабочее подразделение. (Данные из Table2, что представляет из себя справочник всех подразделений, используемых в системе, в том числе данные из Table1 есть в Table2). И это были обыкновенные диалоговые поля с однозначным выбором, то есть 1 поле = 1 значение. Пришёл запрос, что необходимо строить отчёт не по 1 значению, а по нескольким подразделениям, например, 1) 3 значения из Table1 и 1 значение из Table2 или 2) 2 значение из Table1 и 2 значения из Table2 (притом должны быть выведены значения по 4-м пар значений: 1-1, 1-2, 2-1, 2-2, где первое число в паре - введённое значение из Table1, а второе - из Table2). И на эту задачу я придумал то решение, что описал в 1-м сообщении. Но столкнувшись с проблемой решил здесь спросить совета, а вдруг я по незнанию упустил какой-то более простой и правильный вариант решения данной задачки. |
|
31.03.2016, 11:45 | #7 |
Участник
|
Цитата:
3. Подразделение работников. (Table1)
4. Рабочее подразделение (Table2) Т.е. Ваш отчет работает вот так X++: while select table1 { while select table2 { (...) } } X++: while select Table1 join Table2 where Table1.FieldId == Table2.FieldId { (...) }
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
31.03.2016, 12:03 | #8 |
Участник
|
Цитата:
У Вас эти две таблицы никак не связаны между собой? Тот код, что Вы привели - именно так и работает. Т.е. на каждую запись Table1 в отчет выводятся ВСЕ записи Table2? Или все-таки между таблицами есть связь?
И моя идея реализации работает по 1-ому варианту, да. Но если есть что-то более оптимальное - с радостью выслушаю совет.. Последний раз редактировалось Alucardkds; 31.03.2016 в 12:15. |
|
31.03.2016, 13:09 | #9 |
Участник
|
Цитата:
Сообщение от Alucardkds
Да, эти таблицы связаны. В обеих таблицах есть поле DepartmentId и при создании записи в Table1 могут быть созданы только те, по которым есть записи в Table2.
И моя идея реализации работает по 1-ому варианту, да. Но если есть что-то более оптимальное - с радостью выслушаю совет.. X++: void initQuery() { query query1 = new query(); QueryBuildDataSource qbds1, qbds2; ; qbds1= query1.addDataSource(tableNum(Table1)); qbds2= qbds1.addDataSource(tablenum(Table2)); // Если есть явно прописанные Relation на таблицах или в EDT //qbds2.relation(true); // Если нет, то указать объединение явно qbds2.addLink(fieldnum(Table1, DepartmentId), fieldnum(Table2, DepartmentId)) // Явное указание полей, которые будут отображены в форме диалога qbds1.addRange(fieldnum(Table1, Field1)); qbds2.addRange(fieldnum(Table2, Field1)); queryrun1 = new queryRun(query1); } X++: void printSheet1() { ... EDT edt1, edt2; Table1 table1; Table2 table2; ... ; while (queryrun1.next()) { table1 = queryrun1.get(tablenum(Table1)); table2 = queryrun1.get(tableNum(Table2)); edt1 = Table1.Field1; edt2 = Table2.Field2; (...) } }
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: mazzy (2), Alucardkds (1). |
31.03.2016, 14:29 | #10 |
Участник
|
Странно, но с предложенным вариантом ничего не хочет выводить.
Все whil'ы успешно пропускает как будто не сформировал query. Хотя в initQuery заходит и даже успешно запросы делает в датасурс. |
|
31.03.2016, 15:05 | #11 |
Участник
|
1. В методе queryRun() указан сформированный в initQuery() запрос?
2. В методах pack/unpack не выполняется сохранение/восстановление ранее выполненного запроса 3. Вы правильно определили условия объединения таблиц? Может их надо объединять не по DepartmentId? 4. Ну, и проверьте, какой же запрос реально выполняется X++: void printSheet1() { (...) ; //debug // псевдо-скрипт выполняемого запроса info(queryrun1.query().dataSourceNo(1).toString()); while (queryrun1.next()) { (...) } }
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: Alucardkds (1). |
31.03.2016, 17:46 | #12 |
Участник
|
1. В QueryRun всё в порядке.
2. Query у меня пока никак не сохраняется этими методами, не дошёл до этого. Пункты 3. и 4.: Изменил немного код и всё пошло как надо: X++: void initQuery() { query query1 = new query(); QueryBuildDataSource qbds1, qbds2; ; qbds1= query1.addDataSource(tableNum(Table1)); qbds1.firstfast(false); qbds2= qbds1.addDataSource(tablenum(Table2)); qbds2.firstFast(false); //Убрал объединение //qbds2.addLink(fieldnum(Table1, DepartmentId), fieldnum(Table2, DepartmentId)) // Явное указание полей, которые будут отображены в форме диалога qbds1.addRange(fieldnum(Table1, Field1)); qbds2.addRange(fieldnum(Table2, Field1)); queryrun1 = new queryRun(query1); } |
|
19.01.2017, 12:54 | #13 |
Участник
|
Всё это хорошо, пока в объемлющем qbds (qbds1 в вышеприведённом примере) нет группировок.
Если же их добавить, то вложенная таблица (qbds2 / Table2 в вышеприведённом примере) просто перестанет выбираться: при вызове table2 = queryrun1.get(tableNum(Table2)) не будет заполняться table2. Я знаю один выход из такого положения, но он слишком антилиберальный. Если кто-то знает другие, буду благодарен за описание в данной теме. |
|
19.01.2017, 13:12 | #14 |
Участник
|
Цитата:
Если вы хотите получить запрос где таблица сначала группируется, а потом к результату группировки джойнится вложенная таблица, то нужно использовать промежуточный View для группировки и уже этот View соединять с вложенной таблицей. Проясните запрос Последний раз редактировалось S.Kuskov; 19.01.2017 в 13:15. |
|
19.01.2017, 13:24 | #15 |
Участник
|
Цитата:
А с qbds в query ничего не получится. Поля в разделе Group By в дизайне вьюхи будут проигнорированы, а qbds.addGroupByField(viewName, viewField) приведёт к тому, что вложенная таблица не будет выбираться. Так в Ax2009. Подчеркну, что речь идёт о несвязанных таблицах (ни через их Relation, ни через qbds2.addLink() ) , когда надо поучить декартово произведение двух выборок "всё на всё". Последний раз редактировалось AR®; 19.01.2017 в 13:31. |
|
19.01.2017, 13:31 | #16 |
Участник
|
Цитата:
Да какая разница. Наличие или отсутствие relation не меняет принципа соединения таблиц, а влияет только на последующую фильтрацию результата соединения. Последний раз редактировалось S.Kuskov; 19.01.2017 в 13:35. |
|
19.01.2017, 13:39 | #17 |
Участник
|
|
|
19.01.2017, 14:06 | #18 |
Участник
|
Цитата:
Цитата:
Do not specify a field in the Group By element. A view does not use the field information in the Group By element.
Note: If you want to group the records in a view, replace the view data source with a query that has the specified group by information. https://msdn.microsoft.com/en-us/lib...(v=ax.50).aspx |
|
|
За это сообщение автора поблагодарили: AR® (1). |
19.01.2017, 15:08 | #19 |
Участник
|
Во-первых, спасибо за ссылки.
Во-вторых, получилось обойтись без вьюх и "индивидуальных" query для них. Для этого необходимо и достаточно для вложенной таблицы (которую группировать вообще-то было не нужно) сделать qbds.addGroupByField() по всем полям её первичного ключа. Недостаток такого решения в том, что вызовом queryRun.get() нельзя получить поля, не включённые в группировку. |
|
19.01.2017, 16:41 | #20 |
Участник
|
Цитата:
Сообщение от AR®
получилось обойтись без вьюх и "индивидуальных" query для них.
Для этого необходимо и достаточно для вложенной таблицы (которую группировать вообще-то было не нужно) сделать qbds.addGroupByField() по всем полям её первичного ключа. Недостаток такого решения в том, что вызовом queryRun.get() нельзя получить поля, не включённые в группировку. |
|