|  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 не создавал, так что прошу сильно шапками не закидывать. | 
|  |