AXForum  
Go Back   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Forgotten Your Password?
Register Forum Rules FAQ Members List Today's Posts Search

 
 
Thread Tools Search this Thread Display Modes
Old 09.07.2014, 15:29   #1  
iCloud is offline
iCloud
Enjoy!
iCloud's Avatar
MCP
Злыдни
 
195 / 112 (4) +++++
Join Date: 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: Буду благодарен за любую информацию на данную тему.

Last edited by iCloud; 09.07.2014 at 15:34.
This post has been rated by: mazzy (5), Logger (3), S.Kuskov (5), Kabardian (2).
Old 09.07.2014, 15:53   #2  
Zick-Zibn is offline
Zick-Zibn
Участник
 
78 / 38 (2) +++
Join Date: 28.05.2004
Location: Moscow
Почитайте главу 17 Прикладной программный интерфейс
QueryFilter книги Microsoft Dynamics AX 2012 : справочник профессионала, я думаю вы там найдете ответ на свой вопрос.
http://www.navicongroup.ru/ax/book/A...1%8B%D1%85.pdf
This post has been rated by: mazzy (2), Logger (3), S.Kuskov (5), iCloud (1).
Old 09.07.2014, 16:38   #3  
iCloud is offline
iCloud
Enjoy!
iCloud's Avatar
MCP
Злыдни
 
195 / 112 (4) +++++
Join Date: 06.03.2012
Quote:
Originally Posted by Zick-Zibn View Post
Почитайте главу 17 Прикладной программный интерфейс
QueryFilter книги Microsoft Dynamics AX 2012 : справочник профессионала, я думаю вы там найдете ответ на свой вопрос.
http://www.navicongroup.ru/ax/book/A...1%8B%D1%85.pdf
Да я нашел уже, спасибо. Хотелось бы, может, какой-то дискуссии на эту тему.
Old 09.07.2014, 16:43   #4  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,450 / 1792 (66) ++++++++
Join Date: 28.04.2007
Location: Калуга
Quote:
Originally Posted by iCloud View Post
Вопрос: QueryRange правильнее использовать только при простых запросах и когда необходимо поместить в ON фиксированный ключ/релейшн?
Что значит при простых? и что значит правильнее? От этого же не скорость выполнения меняется, а результирующая выборка.
Old 09.07.2014, 16:53   #5  
iCloud is offline
iCloud
Enjoy!
iCloud's Avatar
MCP
Злыдни
 
195 / 112 (4) +++++
Join Date: 06.03.2012
Quote:
Originally Posted by S.Kuskov View Post
Что значит при простых? и что значит правильнее? В результате же не скорость выполнения меняется, а результирующая выборка.
Да именно так, простите за мой нерусский, просто хотелось услышать тонкости использования. Везде сплошь и рядом пишут qbds.addRange() порой не задумываясь о том что результирующая выборка будет не такой.

Тут еще поглядеть методы SysQuery::mergeRanges() и SysQuery::mergeFilters() можно. Для понимания вопроса.
Old 09.07.2014, 17:25   #6  
Zick-Zibn is offline
Zick-Zibn
Участник
 
78 / 38 (2) +++
Join Date: 28.05.2004
Location: Moscow
Quote:
Originally Posted by iCloud View Post
Да я нашел уже, спасибо. Хотелось бы, может, какой-то дискуссии на эту тему.
Я так глубоко в эту тему не вникал, как вы. Единственное где я с этим столкнулся, так это когда по старинке делал программный фильтр на форме с помощью класса QueryBuildRange и все было бы хорошо, когда случайно включил фильтр по сетке. Где я не увидел наложенных фильтром ограничений. После выяснения причин, ответ нашел в книге. Т.е. в DAX 2012 фильтрацию на формах нужно осуществлять с помощью класса QueryFilter. В остальных местах, например классы, можно использовать старый QueryBuildRange.
Old 09.07.2014, 20:09   #7  
iCloud is offline
iCloud
Enjoy!
iCloud's Avatar
MCP
Злыдни
 
195 / 112 (4) +++++
Join Date: 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()).

Last edited by iCloud; 09.07.2014 at 20:14.
This post has been rated by: skuull (1).
Old 10.07.2014, 00:12   #8  
Kabardian is offline
Kabardian
Талантливый разгвоздяй
Kabardian's Avatar
 
424 / 338 (12) ++++++
Join Date: 14.12.2008
Location: Москва
Blog Entries: 14
См. также Проблема с OuterJoin и addRange.
Tags
ax2012, join, outer join, queryfilter, queryrange

 

Similar Threads
Thread Thread Starter Forum Replies Last Post
Опыт: синхронизация справочников через 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

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Рейтинг@Mail.ru
All times are GMT +3. The time now is 01:49.
Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Contacts E-mail, Advertising.