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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 04.07.2006, 16:36   #1  
Russland is offline
Russland
MCTS
Аватар для Russland
MCBMSS
 
267 / 116 (4) +++++
Регистрация: 17.10.2005
Адрес: Донеччина, Україна
Расширенный AddRange и OuterJoin
Итак, в продолжении темы Расширенный AddRange
http://www.axforum.info/forums/showt...693#post108693

Чтобы не быть голословным происследуем поведение таблиц заказов SalesTable & SalesLine.

Связываем таблицы по InnerJoin и пытаемся наложить ограничение по SalesId так, как описано в статье http://www.axaptapedia.com/index.php...ultiple_tables

Допустим, нас интересуют первые несколько заказов.

PHP код:
static void JobAddRangeVsOuterJoin(Args _args)
{
    
Query                   q;
    
QueryRun                qr;
    
QueryBuildDataSource    qbdsqbds2;
    
QueryBuildRange         range;

    
SalesTable              st;
    
SalesLine               sl;

    
SalesId                 _salesId "10";// первые несколько заказов
    
;

    
= new Query();
    
qbds q.addDataSource(tableNum(SalesTable), "SalesTable");
    
q.dataSourceNo(1).addDataSource(tableNum(SalesLine), "SalesLine");

    
q.dataSourceNo(2).addLink(fieldNum(SalesTableSalesId), fieldNum(SalesLineSalesId));
    
q.dataSourceNo(2).joinMode(JOINMODE::InnerJoin);

    
q.dataSourceNo(2).addRange(fieldNum(SalesLineDataAreaId)).value(
        
strFmt('(%1.%2 <= \"%5\")'// SalesTable.SalesId <= первые несколько заказов
        
q.dataSourceTable(tableNum(SalesTable)).name(),
        
fieldStr(SalesTableSalesId),
        
q.dataSourceTable(tableNum(SalesLine)).name(),
        
fieldStr(SalesLine,  SalesId),

        
_salesId ));

        
qr = new QueryRun(q);
        while(
qr.next())
        {
            
st qr.get(tableNum(SalesTable));
            
sl qr.get(tableNum(SalesLine));

            
info(st.SalesId);
        }

Тут необходимо небольшое лирическое отступление.
Просю обратить внимание на строку
q.dataSourceNo(2).addRange(fieldNum(SalesLine, DataAreaId)).value(
.........
SalesTable.SalesId <= первые несколько заказов

Что-за чертовщина? Налаживаем ограничение по SalesTable, а "цепляемся" к SalesLine. Дело в том, что в предыдущем посте стояла задача наложения ограничения одновременно по нескольким таблицам. Следовательно, ничто нам не мешает проделать такой вот финт.

Кроме того, есть пара моментов, не обозначенных(или обозначенных, но вскользь) в вышеприведённой статье.
Во-первых, в примере:

queryBuildRange2.value(strFmt('((%1.%2 == %3) || ((%1.%2 == %4) && (%1.%5 == %6)))',
query.dataSourceTable(tableNum(InventTable)).name(), // InventTable %1
fieldStr(InventTable, ItemType), // ItemType %2
any2int(ItemType::Service), // %3
any2int(ItemType::Item), // %4
fieldStr(InventTable, ItemId), // ItemId %5
fieldStr(InventItemBarCode, ItemId))); // %6

ограничение накладывается на второй источник данных. И неспроста. Дело в том, что если подобная конструкция будет цепляться не на последний источник данных, то Аксапта не сможет "переварить" составленный запрос, она просто "вылетит". Всё потому, что в составленном запросе налагаемое условие по некоему полю может встретится раньше, чем декларация самой таблицы. Что-то вроде

select * from Table1 where table2.Field1 == bla_bla join Table2

Это первый момент.
Второй момент более печальный.

Свяжем таблицы по InnerJoin. Наше условие "подцепляется" ко второму источнику данных.
В этом случае, всё отработается как надо.
Как надо будет работать и в случае "подключения" к первому источнику данных.

А вот OuterJoin (как впрочем, я подозреваю и другие виды связи отличные от InnerJoin) поведёт себя неожиданно.

Итак, устанавливаем
q.dataSourceNo(2).joinMode(JOINMODE::OuterJoin);
и
q.dataSourceNo(1).addRange(fieldNum(SalesLine, DataAreaId)).value(

Всё работает как и надо, а вот

q.dataSourceNo(2).joinMode(JOINMODE::OuterJoin);
и
q.dataSourceNo(2).addRange(fieldNum(SalesLine, DataAreaId)).value( // наш "финт"

выводит чёрти что.

Смотрим запрос в отладчике и видим
LEFT OUTER JOIN SALESLINE B ON ((B.DATAAREAID='bmd') AND ((A.SALESID<=' 10') AND (A.SALESID=B.SALESID)))} WHERE (A.DATAAREAID='bmd') ORDER BY A.DATAAREAID,A.SALESID OPTION(FAST 4)

условие SALESID<=10 расположено до WHERE

А что же было в случае
q.dataSourceNo(2).joinMode(JOINMODE::OuterJoin);
и
q.dataSourceNo(1).addRange(fieldNum(SalesLine, DataAreaId)).value(
?

А вот что
LEFT OUTER JOIN SALESLINE B ON ((B.DATAAREAID='bmd') AND (A.SALESID=B.SALESID))} WHERE ((A.DATAAREAID='bmd') AND (A.SALESID<=' 10')) ORDER BY A.DATAAREAID,A.SALESID OPTION(FAST 4)

Какие выводы можно сделать?
Вывод первый
Используя механизм наложения ограничений по нескольким таблицам необходимо "цепляться" за последний источник данных

Вывод второй
Механизм наложения ограничений по нескольким таблицам корректно отрабатывает с
InnerJoin. С другими видами связи он, увы, работает некорректно.
И как это побороть на ум ничто и не приходит.
__________________

В глухомани, в лесу Несмотря на красу Дни проводит Лиса Патрикевна. Я никак не пойму Отчего, почему Не пускают куму На деревню
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Проблема с OuterJoin и addRange Alex P DAX: Программирование 7 28.02.2014 12:06
AddRange не фильтрует Ихъ бин программикеер DAX: Программирование 6 01.09.2006 14:27
Расширенный AddRange Russland DAX: Программирование 3 04.07.2006 10:49
Можно ли редактировать форму, если на нее наложен addRange? Hans DAX: Программирование 10 22.05.2006 16:35
Опять про OuterJoin нескольких таблиц murad DAX: Программирование 1 15.05.2006 10:26

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 10:55.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.