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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 09.07.2014, 15:29   #1  
iCloud is offline
iCloud
Enjoy!
Аватар для iCloud
MCP
Злыдни
 
195 / 112 (4) +++++
Регистрация: 06.03.2012
Post 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
Если вначале раскомментировать 2 строки которые реализуют добавление фильтра через класс QueryRange, то результат запроса таков:
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'}))
Если же запустить данный Job без изменений, тем самым реализовать добавление
фильтра через класс 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  
Zick-Zibn is offline
Zick-Zibn
Участник
 
78 / 38 (2) +++
Регистрация: 28.05.2004
Адрес: Moscow
Почитайте главу 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  
iCloud is offline
iCloud
Enjoy!
Аватар для iCloud
MCP
Злыдни
 
195 / 112 (4) +++++
Регистрация: 06.03.2012
Цитата:
Сообщение от 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  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от iCloud Посмотреть сообщение
Вопрос: QueryRange правильнее использовать только при простых запросах и когда необходимо поместить в ON фиксированный ключ/релейшн?
Что значит при простых? и что значит правильнее? От этого же не скорость выполнения меняется, а результирующая выборка.
Старый 09.07.2014, 16:53   #5  
iCloud is offline
iCloud
Enjoy!
Аватар для iCloud
MCP
Злыдни
 
195 / 112 (4) +++++
Регистрация: 06.03.2012
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Что значит при простых? и что значит правильнее? В результате же не скорость выполнения меняется, а результирующая выборка.
Да именно так, простите за мой нерусский, просто хотелось услышать тонкости использования. Везде сплошь и рядом пишут qbds.addRange() порой не задумываясь о том что результирующая выборка будет не такой.

Тут еще поглядеть методы SysQuery::mergeRanges() и SysQuery::mergeFilters() можно. Для понимания вопроса.
Старый 09.07.2014, 17:25   #6  
Zick-Zibn is offline
Zick-Zibn
Участник
 
78 / 38 (2) +++
Регистрация: 28.05.2004
Адрес: Moscow
Цитата:
Сообщение от iCloud Посмотреть сообщение
Да я нашел уже, спасибо. Хотелось бы, может, какой-то дискуссии на эту тему.
Я так глубоко в эту тему не вникал, как вы. Единственное где я с этим столкнулся, так это когда по старинке делал программный фильтр на форме с помощью класса QueryBuildRange и все было бы хорошо, когда случайно включил фильтр по сетке. Где я не увидел наложенных фильтром ограничений. После выяснения причин, ответ нашел в книге. Т.е. в DAX 2012 фильтрацию на формах нужно осуществлять с помощью класса QueryFilter. В остальных местах, например классы, можно использовать старый QueryBuildRange.
Старый 09.07.2014, 20:09   #7  
iCloud is offline
iCloud
Enjoy!
Аватар для iCloud
MCP
Злыдни
 
195 / 112 (4) +++++
Регистрация: 06.03.2012
Еще, для справки:
Например, если запаковать 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--;
    }
}
Получается, что после того как QueryRun был инициализирован new QueryRun(q) (формируем запрос с помощью addRange) все Range которые попали после оператора WHERE отныне есть фильтры и перебрать их возможно только вышеуказанным способом (имею ввиду через queryFilterCount()).

Последний раз редактировалось iCloud; 09.07.2014 в 20:14.
За это сообщение автора поблагодарили: skuull (1).
Старый 10.07.2014, 00:12   #8  
Kabardian is offline
Kabardian
Талантливый разгвоздяй
Аватар для Kabardian
 
424 / 338 (12) ++++++
Регистрация: 14.12.2008
Адрес: Москва
Записей в блоге: 14
См. также Проблема с OuterJoin и addRange.
Теги
ax2012, join, outer join, queryfilter, queryrange

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Опыт: синхронизация справочников через AIF в AX2012 EVGL DAX: Функционал 14 28.08.2020 17:52
Ax3 - Модуль Учет затрат egorych DAX: Функционал 15 12.12.2013 17:58
emeadaxsupport: Inventory closing differences between AX4.0 and AX2012 using weighted average costing method Blog bot DAX Blogs 0 27.12.2012 19:11
axblog4u: Display Web Image Content in Forms using Dynamics AX2012 Blog bot DAX Blogs 0 28.05.2012 19:12
ukax: Microsoft Dynamics AX2012 - Partner Update Briefing Blog bot DAX Blogs 0 23.07.2011 20:15

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

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

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