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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 19.06.2017, 15:54   #1  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Запрос ИЛИ в 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  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
могу ошибаться, но если установлен group by, то он должен быть установлен у всех датасорсов.

можно совет?
не пишите запросы в коде. создайте запрос в AOT.
пропишите в коде постоянные relation, value

в коде пишите
X++:
Query q = new Query(querystr(mySuperQuery));
дальше делайте с уже созданным query устанавливайте rangevalue
например при помощи SysQuery::findOrCreateRange()

геморроя будет намного меньше.
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 16:08   #3  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
А с текстом запроса что происходит?
X++:
info(qbdsItt.ToString());
Как вариант:

Вместо exists join попробовать inner join. В данном случае вроде бы уникальность записей в InventLocation позволяет.

Возможно использовать промежуточное View
За это сообщение автора поблагодарили: mazzy (2), smailik (1).
Старый 19.06.2017, 16:11   #4  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
X++:
    qbdsIt = qbdsItl.addDataSource(tableNum(InventTable));
    qbdsIt.relations(true);
    qbdsIt.joinMode(joinMode::InnerJoin);
    qbdsIt.orderMode(OrderMode::GROUPBY);
Так я тоже пробовал. Не помогло. Изначально опирался на http://www.axaptapedia.com/Expressions_in_query_ranges
Если больше вариантов не будет, то буду пробовать создавать query в AOT.
Старый 19.06.2017, 16:16   #5  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Замена на 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  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от smailik Посмотреть сообщение
AND ((((InventLocation_1.InventLocationType == 8) || (InventLocation_2.InventLocationType == 8))))
это неправильная конструкция для SQL
вместо || в строке должен быть OR
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 16:36   #7  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Если в range "||" заменяю на "OR" то получаю ошибку
Ошибка расширенного диапазона запроса: Ожидается правая круглая скобка рядом с 48.
Старый 19.06.2017, 16:43   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
и в SQL используется = вместо ==
))
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 16:49   #9  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
SQL конечно SQL-ем, но тот у меня не прямой запрос к базе, а построение query. Я конечно попробовал. Попытка - не пытка. Ошибка та же самая, только в конце "с 47."
Старый 19.06.2017, 17:00   #10  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Если написать вот так
X++:
qbrDataAreaId.value(strFmt('(%1.%3 = %4) OR (%2.%3 = %4)', ...
то ошибки не возникает, но и результат работы не верный.
Старый 19.06.2017, 17:07   #11  
bitter is offline
bitter
Участник
 
15 / 19 (1) ++
Регистрация: 12.04.2015
Попробуйте таким образом:
X++:
qbrDataAreaId.value(strFmt('((%1.%3 = %4) || (%2.%3 = %4))', ...
Полезная ссылка по этой теме.
Старый 19.06.2017, 17:11   #12  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Вашей ссылкой я уже пользовался. Она менее полезна чем та которую писал я, так как в этот пример ИЛИ для одной таблицы.
Предложенный вариант, тоже не помог.
Старый 19.06.2017, 17:17   #13  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
в общем, странно.
попробуйте упростить свой запрос, чтобы выяснить причину. мне кажется, что проблема не в ИЛИ.
попробуйте создать запрос в AOT, а в коде только менять range

вот еще старые-старые комментарии внизу http://axapta.mazzy.ru/lib/search/
оно должно работать.
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 17:18   #14  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,953 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
У вас 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  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,953 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
А вообще для начала неплохо бы подсмотреть что уходит реально на SQL и от этого плясать.
Конечно включить query.literals(1)
Старый 19.06.2017, 17:24   #16  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от 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))))
1. у вас точно есть enum ItemType со значением 8? просто в стандартной 2012 такого нет
2. обратите внимание на название таблиц.
в запросе у вас ДВЕ inventLocation, а в условии название таблицы InventLocation_1 и InventLocation_2.

Стройте запросы в АОТ!
в коде пишите только одну строку Query q = new Query(querystr(mySuperQuery));
и не парьтесь.
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 17:32   #17  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Цитата:
Сообщение от Logger Посмотреть сообщение
Вытягивать весь запрос в линейку
У меня ведь и так в линейку. К шапкам - строки, к строкам - номенклатуры, но как не крути склады то я только к шапке могу прицепить.
Старый 19.06.2017, 17:34   #18  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
mazzy, 1- да, 2- меня это тоже смущает, но стоит убрать InventTable из query и все работает, не смотря на такой странный вид.
Запрос в AOT - хорошо, но как в нем прописать такой range между двумя таблицами?
Старый 19.06.2017, 17:43   #19  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от mazzy Посмотреть сообщение
в коде пишите
X++:
Query q = new Query(querystr(mySuperQuery));
дальше делайте с уже созданным query устанавливайте rangevalue
например при помощи SysQuery::findOrCreateRange()

геморроя будет намного меньше.
другими словами, НЕ ОБЯЗАТЕЛЬНО СОЗДАВАТЬ запрос С НУЛЯ в коде.

пишите что-то вроде такого:
X++:
Query q = new Query(querystr(mySuperQuery));
SysQuery::findOrCreateRange(q.datasourceTable(tablenum(...)), fieldnum(...)).value(...);
все.
не надо многоэтажных конструкций. и вы всегда уверены, что датасорсы и проперти расставлены правильно с точки зрения аксапты.
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 18:18   #20  
smailik is offline
smailik
Участник
Аватар для smailik
 
250 / 70 (3) ++++
Регистрация: 10.04.2012
Адрес: Москва
Создал 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 не создавал, так что прошу сильно шапками не закидывать.
Вложения
Тип файла: xpo myQuery.xpo (2.9 Кб, 270 просмотров)
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Query для HcmPosition (запрос по таблице, соссылкой на себя же) Music DAX: Программирование 9 07.07.2016 14:54
emeadaxsupport: Microsoft Dynamics AX general performance analysis scripts page 5 Blog bot DAX Blogs 0 01.09.2014 14:11
Вложенный запрос SQL с помощью великого Query user_ax DAX: Программирование 9 07.10.2013 14:00
like запрос с использованием query Vadik Shiryakoff DAX: Программирование 7 13.03.2006 12:05

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 09:35.