Итак, в продолжении темы
Расширенный 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 qbds, qbds2;
QueryBuildRange range;
SalesTable st;
SalesLine sl;
SalesId _salesId = "10";// первые несколько заказов
;
q = new Query();
qbds = q.addDataSource(tableNum(SalesTable), "SalesTable");
q.dataSourceNo(1).addDataSource(tableNum(SalesLine), "SalesLine");
q.dataSourceNo(2).addLink(fieldNum(SalesTable, SalesId), fieldNum(SalesLine, SalesId));
q.dataSourceNo(2).joinMode(JOINMODE::InnerJoin);
q.dataSourceNo(2).addRange(fieldNum(SalesLine, DataAreaId)).value(
strFmt('(%1.%2 <= \"%5\")', // SalesTable.SalesId <= первые несколько заказов
q.dataSourceTable(tableNum(SalesTable)).name(),
fieldStr(SalesTable, SalesId),
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. С другими видами связи он, увы, работает некорректно.
И как это побороть на ум ничто и не приходит.