09.07.2014, 15:29 | #1 |
Enjoy!
|
QueryRange и QueryFilter [AX2012]
День добрый. Наткнулся на ранее не изведанную мною тему.
Начну с наглядного, есть Job, внутри запрос реализующий InnerJoin и OuterJoin. X++: QueryRun qr; Query query = new Query(); QueryBuildDataSource qbdsEcoResProduct, qcoEcoResProductDimensionGroupProduct, qcoEcoResProductTranslation, qbdsInventTable, qbdsRetailAssortmentExploded; RetailStoreTable _storeTable; TransDate _effectiveDate = systemDateGet(); qbdsEcoResProduct = query.addDataSource(tableNum(EcoResProduct)); qbdsInventTable = qbdsEcoResProduct.addDataSource(tableNum(InventTable)); qbdsInventTable.joinMode(JoinMode::InnerJoin); //qbdsInventTable.fetchMode(QueryFetchMode::One2One); qbdsInventTable.addLink(fieldNum(EcoResProduct, RecId), fieldNum(InventTable, Product), qbdsEcoResProduct.name()); qbdsRetailAssortmentExploded = qbdsInventTable.addDataSource(tableNum(RetailAssortmentExploded)); qbdsRetailAssortmentExploded.joinMode(JoinMode::OuterJoin); qbdsRetailAssortmentExploded.relations(true); qbdsRetailAssortmentExploded.addRange(fieldNum(RetailAssortmentExploded, OMOperatingUnitId)).value(queryValue(_storeTable.OMOperatingUnitID)); // --> User: DBOwner //qbdsRetailAssortmentExploded.addRange(fieldNum(RetailAssortmentExploded, ValidFrom)).value(queryRange(dateNull(), _effectiveDate)); //qbdsRetailAssortmentExploded.addRange(fieldNum(RetailAssortmentExploded, ValidTo)).value(queryRange(_effectiveDate, datemax())); query.addQueryFilter(qbdsRetailAssortmentExploded, fieldStr(RetailAssortmentExploded, ValidFrom)).value(queryRange(dateNull(), systemDateGet())); query.addQueryFilter(qbdsRetailAssortmentExploded, fieldStr(RetailAssortmentExploded, ValidTo)).value(queryRange(systemDateGet(), datemax())); // <-- User: DBOwner X++: SELECT * FROM EcoResProduct(EcoResProduct_1) JOIN * FROM InventTable(InventTable_1) ON EcoResProduct.RecId = InventTable.Product OUTER JOIN * FROM RetailAssortmentExploded(RetailAssortmentExploded_1) ON InventTable.ItemId = RetailAssortmentExploded.ItemId AND ((OMOperatingUnitId = 0)) AND ((ValidFrom<={ts '2014-07-09 00:00:00.000'})) AND ((ValidTo>={ts '2014-07-09 00:00:00.000'} AND ValidTo<={ts '2154-12-31 00:00:00.000'})) фильтра через класс QueryFilter то фильтры гарантированно уйдут после оператора WHERE: X++: SELECT * FROM EcoResProduct(EcoResProduct_1) JOIN * FROM InventTable(InventTable_1) ON EcoResProduct.RecId = InventTable.Product OUTER JOIN * FROM RetailAssortmentExploded(RetailAssortmentExploded_1) ON InventTable.ItemId = RetailAssortmentExploded.ItemId AND ((OMOperatingUnitId = 0)) WHERE ((RetailAssortmentExploded(RetailAssortmentExploded_1).ValidFrom<={ts '2014-07-09 00:00:00.000'})) AND ((RetailAssortmentExploded(RetailAssortmentExploded_1).ValidTo>={ts '2014-07-09 00:00:00.000'} AND ValidTo<={ts '2154-12-31 00:00:00.000'})) Для inner join никакой разницы между ними нет; для outer join записи, не удовлетворяющие условиям выражения ON, включаются в результирующую выборку, а записи, не удовлетворяющие условиям выражения where, не включаются. Использование QueryFilter гарантированно опускает условия выборки после WHERE. Вопрос: QueryRange правильнее использовать только при простых запросах и когда необходимо поместить в ON фиксированный ключ/релейшн? UPD: Буду благодарен за любую информацию на данную тему. Последний раз редактировалось iCloud; 09.07.2014 в 15:34. |
|
|
За это сообщение автора поблагодарили: mazzy (5), Logger (3), S.Kuskov (5), Kabardian (2). |
09.07.2014, 15:53 | #2 |
Участник
|
Почитайте главу 17 Прикладной программный интерфейс
QueryFilter книги Microsoft Dynamics AX 2012 : справочник профессионала, я думаю вы там найдете ответ на свой вопрос. http://www.navicongroup.ru/ax/book/A...1%8B%D1%85.pdf |
|
|
За это сообщение автора поблагодарили: mazzy (2), Logger (3), S.Kuskov (5), iCloud (1). |
09.07.2014, 16:38 | #3 |
Enjoy!
|
Цитата:
Сообщение от Zick-Zibn
Почитайте главу 17 Прикладной программный интерфейс
QueryFilter книги Microsoft Dynamics AX 2012 : справочник профессионала, я думаю вы там найдете ответ на свой вопрос. http://www.navicongroup.ru/ax/book/A...1%8B%D1%85.pdf |
|
09.07.2014, 16:43 | #4 |
Участник
|
|
|
09.07.2014, 16:53 | #5 |
Enjoy!
|
Цитата:
Тут еще поглядеть методы SysQuery::mergeRanges() и SysQuery::mergeFilters() можно. Для понимания вопроса. |
|
09.07.2014, 17:25 | #6 |
Участник
|
Я так глубоко в эту тему не вникал, как вы. Единственное где я с этим столкнулся, так это когда по старинке делал программный фильтр на форме с помощью класса QueryBuildRange и все было бы хорошо, когда случайно включил фильтр по сетке. Где я не увидел наложенных фильтром ограничений. После выяснения причин, ответ нашел в книге. Т.е. в DAX 2012 фильтрацию на формах нужно осуществлять с помощью класса QueryFilter. В остальных местах, например классы, можно использовать старый QueryBuildRange.
|
|
09.07.2014, 20:09 | #7 |
Enjoy!
|
Еще, для справки:
Например, если запаковать QueryRun в табличное поле с типом Container, например из формы SysQueryForm. То после, распаковав QueryRun - перебрать ренджи можно только с помощью queryFilterCount(): X++: //Пакуем все фильтры в map if(SysQuery::queryHasFilters(sourceQuery)) { filtersCount = sourceQuery.queryFilterCount(); while(filtersCount) { qFilter = sourceQuery.queryFilter(filtersCount); Debug::assert(qFilter != null); tableId = qFilter.dataSource().table(); fieldId = fieldName2id(tableId, qFilter.field()); queryValue = qFilter.value(); if(! filterMap.exists([tableId, fieldId])) filterMap.insert([tableId, fieldId], queryValue); filtersCount--; } } Последний раз редактировалось iCloud; 09.07.2014 в 20:14. |
|
|
За это сообщение автора поблагодарили: skuull (1). |
10.07.2014, 00:12 | #8 |
Талантливый разгвоздяй
|
См. также Проблема с OuterJoin и addRange.
|
|
Теги |
ax2012, join, outer join, queryfilter, queryrange |
|
|