19.06.2017, 15:54 | #1 |
Участник
|
Запрос ИЛИ в query
Всем доброго дня. AX 4. Прошу помощи вот в каком вопросе. Создаю query как написано ниже. Если запускать так то все работает. Но если раскоментировать присоединение InventTable, то система начинает игнорировать наложение range по InventLocationType.
Может кто-нибудь сталкивался с подобным? Посоветуйте как это победить? X++: query = new Query(); qbdsItt = query.addDataSource(tablenum(InventTransferTable), "Transfer"); qbdsItt.orderMode(OrderMode::GroupBy); qbdsItt.addRange(fieldnum(InventTransferTable, ReceiveDate)).value(strfmt('%1..%2', fromDate, toDate)); qbdsItt.addRange(fieldnum(InventTransferTable, TransferStatus)).value(QueryValue(InventTransferStatus::Received)); qbdsItt.addRange(fieldnum(InventTransferTable, InventLocationIdFrom)).value(inventLocationIdFrom); qbdsItl = qbdsItt.addDataSource(tablenum(InventTransferLine)); qbdsItl.addLink(fieldnum(InventTransferLine , TransferId), fieldnum(InventTransferTable, TransferId)); qbdsItl.joinMode(JoinMode::InnerJoin); qbdsItl.orderMode(OrderMode::GROUPBY); qbdsItl.fetchMode(QueryFetchMode::One2One); /* qbdsIt = qbdsItl.addDataSource(tableNum(InventTable)); qbdsIt.relations(true); qbdsIt.joinMode(joinMode::InnerJoin); */ if (inventLocationType != InventLocationType::Standard) { qbdsInventLocationFrom = qbdsItt.addDataSource(tablenum(InventLocation)); qbdsInventLocationFrom.addLink(fieldNum(InventTransferTable, InventLocationIdFrom), fieldNum(InventLocation, InventLocationId)); qbdsInventLocationFrom.joinMode(JoinMode::ExistsJoin); qbdsInventLocationFrom.fetchMode(QueryFetchMode::One2One); qbdsInventLocationTo = qbdsItt.addDataSource(tableNum(InventLocation)); qbdsInventLocationTo.addLink(fieldNum(InventTransferTable, InventLocationIdTo), fieldNum(InventLocation, InventLocationId)); qbdsInventLocationTo.joinMode(JoinMode::ExistsJoin); qbdsInventLocationTo.fetchMode(QueryFetchMode::One2One); qbrDataAreaId = qbdsInventLocationTo.addRange(fieldNum(InventLocation, DataAreaId)); qbrDataAreaId.value(strFmt('((%1.%3 == %4) || (%2.%3 == %4))', qbdsInventLocationFrom.name(), qbdsInventLocationTo.name(), fieldStr(InventLocation, InventLocationType), any2int(inventLocationType))); } queryRun = new QueryRun(query); rowCount = SysQuery::countLoops(queryRun); |
|
19.06.2017, 16:08 | #2 |
Участник
|
могу ошибаться, но если установлен group by, то он должен быть установлен у всех датасорсов.
можно совет? не пишите запросы в коде. создайте запрос в AOT. пропишите в коде постоянные relation, value в коде пишите X++: Query q = new Query(querystr(mySuperQuery)); например при помощи SysQuery::findOrCreateRange() геморроя будет намного меньше. |
|
19.06.2017, 16:08 | #3 |
Участник
|
А с текстом запроса что происходит?
X++: info(qbdsItt.ToString()); Вместо exists join попробовать inner join. В данном случае вроде бы уникальность записей в InventLocation позволяет. Возможно использовать промежуточное View |
|
|
За это сообщение автора поблагодарили: mazzy (2), smailik (1). |
19.06.2017, 16:11 | #4 |
Участник
|
X++: qbdsIt = qbdsItl.addDataSource(tableNum(InventTable)); qbdsIt.relations(true); qbdsIt.joinMode(joinMode::InnerJoin); qbdsIt.orderMode(OrderMode::GROUPBY); Если больше вариантов не будет, то буду пробовать создавать query в AOT. |
|
19.06.2017, 16:16 | #5 |
Участник
|
Замена на inner join ничего не дала.
Текст запроса: SELECT * FROM InventTransferTable WHERE ((ReceiveDate>={ts '2017-05-20 00:00:00.000'} AND ReceiveDate<={ts '2017-06-19 00:00:00.000'})) AND ((TransferStatus = 2)) AND ((InventLocationIdFrom = N'242')) JOIN * FROM InventTransferLine WHERE InventTransferTable.TransferId = InventTransferLine.TransferId JOIN * FROM InventTable WHERE InventTransferLine.ItemId = InventTable.ItemId JOIN * FROM InventLocation WHERE InventTransferTable.InventLocationIdFrom = InventLocation.InventLocationId JOIN * FROM InventLocation WHERE InventTransferTable.InventLocationIdTo = InventLocation.InventLocationId AND ((((InventLocation_1.InventLocationType == 8) || (InventLocation_2.InventLocationType == 8)))) |
|
19.06.2017, 16:33 | #6 |
Участник
|
Цитата:
вместо || в строке должен быть OR |
|
19.06.2017, 16:36 | #7 |
Участник
|
Если в range "||" заменяю на "OR" то получаю ошибку
Ошибка расширенного диапазона запроса: Ожидается правая круглая скобка рядом с 48. |
|
19.06.2017, 16:43 | #8 |
Участник
|
и в SQL используется = вместо ==
)) |
|
19.06.2017, 16:49 | #9 |
Участник
|
SQL конечно SQL-ем, но тот у меня не прямой запрос к базе, а построение query. Я конечно попробовал. Попытка - не пытка. Ошибка та же самая, только в конце "с 47."
|
|
19.06.2017, 17:00 | #10 |
Участник
|
Если написать вот так
X++: qbrDataAreaId.value(strFmt('(%1.%3 = %4) OR (%2.%3 = %4)', ... |
|
19.06.2017, 17:07 | #11 |
Участник
|
Попробуйте таким образом:
X++: qbrDataAreaId.value(strFmt('((%1.%3 = %4) || (%2.%3 = %4))', ... |
|
19.06.2017, 17:11 | #12 |
Участник
|
Вашей ссылкой я уже пользовался. Она менее полезна чем та которую писал я, так как в этот пример ИЛИ для одной таблицы.
Предложенный вариант, тоже не помог. |
|
19.06.2017, 17:17 | #13 |
Участник
|
в общем, странно.
попробуйте упростить свой запрос, чтобы выяснить причину. мне кажется, что проблема не в ИЛИ. попробуйте создать запрос в AOT, а в коде только менять range вот еще старые-старые комментарии внизу http://axapta.mazzy.ru/lib/search/ оно должно работать. |
|
19.06.2017, 17:18 | #14 |
Участник
|
У вас Query двоится. И одна из веток отсекается.
Против такого неплохо помогает такой финт: Вытягивать весь запрос в линейку qbdsItt - qbdsItl - qbdsIt - qbdsInventLocationFrom - qbdsInventLocationTo т.е. в таком порядке делать AddDatasource. А связи прописать через вызов addlink() указав 3-м параметром имя реального датасорса к которому линкуем. Такой вариант всегда для inner join работал (но не для outer) |
|
|
За это сообщение автора поблагодарили: mazzy (2), smailik (1), S.Kuskov (2). |
19.06.2017, 17:20 | #15 |
Участник
|
А вообще для начала неплохо бы подсмотреть что уходит реально на SQL и от этого плясать.
Конечно включить query.literals(1) |
|
19.06.2017, 17:24 | #16 |
Участник
|
Цитата:
Сообщение от smailik
Замена на inner join ничего не дала.
Текст запроса: SELECT * FROM InventTransferTable WHERE ((ReceiveDate>={ts '2017-05-20 00:00:00.000'} AND ReceiveDate<={ts '2017-06-19 00:00:00.000'})) AND ((TransferStatus = 2)) AND ((InventLocationIdFrom = N'242')) JOIN * FROM InventTransferLine WHERE InventTransferTable.TransferId = InventTransferLine.TransferId JOIN * FROM InventTable WHERE InventTransferLine.ItemId = InventTable.ItemId JOIN * FROM InventLocation WHERE InventTransferTable.InventLocationIdFrom = InventLocation.InventLocationId JOIN * FROM InventLocation WHERE InventTransferTable.InventLocationIdTo = InventLocation.InventLocationId AND ((((InventLocation_1.InventLocationType == 8) || (InventLocation_2.InventLocationType == 8)))) 2. обратите внимание на название таблиц. в запросе у вас ДВЕ inventLocation, а в условии название таблицы InventLocation_1 и InventLocation_2. Стройте запросы в АОТ! в коде пишите только одну строку Query q = new Query(querystr(mySuperQuery)); и не парьтесь. |
|
19.06.2017, 17:32 | #17 |
Участник
|
|
|
19.06.2017, 17:34 | #18 |
Участник
|
mazzy, 1- да, 2- меня это тоже смущает, но стоит убрать InventTable из query и все работает, не смотря на такой странный вид.
Запрос в AOT - хорошо, но как в нем прописать такой range между двумя таблицами? |
|
19.06.2017, 17:43 | #19 |
Участник
|
Цитата:
пишите что-то вроде такого: X++: Query q = new Query(querystr(mySuperQuery)); SysQuery::findOrCreateRange(q.datasourceTable(tablenum(...)), fieldnum(...)).value(...); не надо многоэтажных конструкций. и вы всегда уверены, что датасорсы и проперти расставлены правильно с точки зрения аксапты. |
|
19.06.2017, 18:18 | #20 |
Участник
|
Создал query в АОТ.
Сейчас код выглядит так. X++: query = new Query(querystr(myQuery)); qbdsItt = SysQuery::findOrCreateDataSource(query, tableNum(InventTransferTable)); qbdsItt.addRange(fieldnum(InventTransferTable, ReceiveDate)).value(strfmt('%1..%2', fromDate, toDate)); qbdsItt.addRange(fieldnum(InventTransferTable, TransferStatus)).value(QueryValue(InventTransferStatus::Received)); qbdsItt.addRange(fieldnum(InventTransferTable, InventLocationIdFrom)).value(inventLocationId); if (inventLocationType != InventLocationType::Standard) { qbdsInventLocationTo = SysQuery::findOrCreateDataSource(query, tableNum(InventLocation), tableNum(InventTransferTable)); qbrDataAreaId = qbdsInventLocationTo.addRange(fieldNum(InventLocation, DataAreaId)); qbrDataAreaId.value(strFmt('((%1.%3 = %4) || (%2.%3 = %4))', 'InventLocationTo', 'InventLocationFrom', fieldStr(InventLocation, InventLocationType), any2int(inventLocationType))); } //info(qbdsItt.ToString()); queryRun = new QueryRun(query); rowCount = SysQuery::countLoops(queryRun); Да этого момента в AOT query не создавал, так что прошу сильно шапками не закидывать. |
|