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

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

SysQuery::findOrCreateDataSource(query добавляет в корень.
и не задает связь, насколько я помню.

создайте ВЕСЬ запрос в АОТ. избавьте себя от необходимости манипулировать с датасорсами.
в коде устанавливайте только range.value.

даю маячок - в АОТ можно создать ДВА запроса. один для InventLocationType::Standard, другой для прочих типов.
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 18:52   #3  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
В общем, код должен выглядеть примерно так:

X++:
Query query = new Query(querystr(myQuery));
QueryBuildDataSource qbdsItt = query.datasourcetable(tableNum(InventTransferTable)); // никаких Create! только читаем
QueryBuildDataSource qbdsIlTo = query.datasourcetable(tableNum(InventLocation),1); // первый по порядку. Или query.datasource("InventLocationTo") позволяет получить датасорс по имени
QueryBuildDataSource qbdsIlFrom = query.datasourcetable(tableNum(InventLocation),2); // второй по порядку. Или query.datasource

Debug::assert(qbdsItt);
Debug::assert(qbdsIlTo);
Debug::assert(qbdsIlFrom);

    qbdsItt.addRange(fieldnum(InventTransferTable, ReceiveDate)).value(SysQuery::range(fromDate, toDate));
    qbdsItt.addRange(fieldnum(InventTransferTable, TransferStatus)).value(SysQuery::value(InventTransferStatus::Received)); // может быть, лучше сразу задать в запросе в АОТ
    qbdsItt.addRange(fieldnum(InventTransferTable, InventLocationIdFrom)).value(inventLocationId);

    if (inventLocationType != InventLocationType::Standard)
    {
        SysQuery::findOrCreateRange(qbdsIlTo, fieldNum(InventLocation, DataAreaId))
            .value(strFmt('((%1.%3 = %4) || (%2.%3 = %4))',
                qbdsIlTo.name(),
                qbdsIlFrom.name(),
                fieldStr(InventLocation, InventLocationType),
                any2int(inventLocationType)));
    }

    //info(qbdsItt.ToString());

    queryRun = new QueryRun(query);

    rowCount = SysQuery::countLoops(queryRun);
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 19.06.2017 в 18:59.
Старый 19.06.2017, 18:56   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Да, насчет количества строк.
Цитата:
Сообщение от smailik Посмотреть сообщение
При запуске висит на подсчете количества строк.
у меня нет под рукой акс4, но насколько я понимаю из текстового файла с запросом, вы не задали Relation между датасорсами.
вот там и происходило декартово произведение.

без InventTable в запросе получается три несвязанные таблицы, насколько я понимаю.
как раз для понимания и нужен результат q.datasource().tostring().
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 22:24   #5  
dim-gin is offline
dim-gin
Участник
 
41 / 30 (2) +++
Регистрация: 15.04.2014
Адрес: СПб
Если брать исходный текст с Query, то можно попробовать указать fetch mode 1:1 явно у всех DS (кроме первого, разумеется).

Если я правильно понял задачу, требуется что-то типа такого:
X++:
    Query                   q;
    QueryBuildDataSource    qbdsIJT, qbdsIJTr, qbdsIL,
                            qbdsIT;
    QueryBuildRange         qbr;
    QueryRun                qr;
    
    ;

    q = new Query();

    // смысл group by мне непонятен
    qbdsIJT = q.addDataSource(tablenum(InventJournalTable));
//    qbdsIJT.orderMode(OrderMode::GroupBy);
    qbdsIJT.addSelectionField(fieldNum(InventJournalTable, JournalId), SelectionField::Database);
    qbdsIJT.addSelectionField(fieldNum(InventJournalTable, InventLocationId), SelectionField::Database);
    qbdsIJT.addSelectionField(fieldNum(InventJournalTable, InventLocationIdTo), SelectionField::Database);
    qbdsIJT.addRange(fieldnum(InventJournalTable, JournalNameId)).value('ПРС');

    qbdsIJTr = qbdsIJT.addDataSource(tablenum(InventJournalTrans));
    qbdsIJTr.addSelectionField(fieldNum(InventJournalTrans, InventTransId), SelectionField::Database);
    qbdsIJTr.addSelectionField(fieldNum(InventJournalTrans, ItemId), SelectionField::Database);
    qbdsIJTr.addSelectionField(fieldNum(InventJournalTrans, InventDimId), SelectionField::Database);
    qbdsIJTr.addSelectionField(fieldNum(InventJournalTrans, Qty), SelectionField::Database);
    qbdsIJTr.relations(true);
    qbdsIJTr.joinMode(JoinMode::InnerJoin);
//    qbdsIJTr.orderMode(OrderMode::GROUPBY);
    qbdsIJTr.fetchMode(QueryFetchMode::One2One);

    qbdsIT = qbdsIJTr.addDataSource(tableNum(InventTable));
    qbdsIT.relations(true);
    qbdsIT.addSelectionField(fieldNum(InventTable, ItemName), SelectionField::Database);
    qbdsIT.addSelectionField(fieldNum(InventTable, ItemGroupId), SelectionField::Database);
    qbdsIT.joinMode(joinMode::InnerJoin);
//    qbdsItl.orderMode(OrderMode::GROUPBY);
    qbdsIT.fetchMode(QueryFetchMode::One2One);

    // можно объединить 2 DS в одну конструкцию
    qbdsIT = qbdsIJT.addDataSource(tableNum(InventLocation));
    qbdsIT.fetchMode(QueryFetchMode::One2One);
    qbdsIT.joinMode(JoinMode::ExistsJoin);
    qbdsIT.relations(false);
    // это на самом деле relation
    qbr = qbdsIT.addRange(fieldNum(InventLocation, InventLocationId));
    qbr.value(strFmt('(%1.%2 = %4.%5) || (%1.%3 = %4.%5)',
        qbdsIJT.name(), fieldStr(InventJournalTable, InventLocationId), fieldStr(InventJournalTable, InventLocationIdTo),
        qbdsIT.name(), fieldStr(InventLocation, InventLocationId)) );
    // прочие условия (на справочник складов)
    //qbdsIT.addRange(fieldNum(...

    // проверка, что не потерялся какой-нибудь DS
    qr = new QueryRun(q);
    if (qr.next())
        info(strFmt('%1 %2 %3',
            qr.get(tableNum(InventJournalTable)).(fieldNum(InventJournalTable, JournalId)),
            qr.get(tableNum(InventJournalTrans)).(fieldNum(InventJournalTrans, InventTransId)),
            qr.get(tableNum(InventTable)).(fieldNum(InventTable, ItemName))
            ));

    info('DAX query: '+qbdsIJT.toString());
    info(strFmt('Query qty: %1', SysQuery::qrCount(new QueryRun(q))));
В трёшке и 2009й работает. В примере объекты заменены на скл.журналы, но конструкция та же.

P.S. В стандарте, конечно же, нет полей со складами в шапке скл.журналов, добавлены вручную.

Пока строчил, уже всё порешали)))

Последний раз редактировалось dim-gin; 19.06.2017 в 22:28. Причина: опоздал с сообщением
За это сообщение автора поблагодарили: mazzy (2), smailik (1), alex55 (1).
Старый 19.06.2017, 22:32   #6  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
group by там похоже, потому что они что-то считают (судя по промелькнувшему SysQuery::count)
похоже просто код не полный.

да, проблема как раз в нескольких existsJoin в подчиненных таблицах.
с одним existsJoin никаких проблем

Цитата:
Сообщение от dim-gin Посмотреть сообщение
X++:
    // можно объединить 2 DS в одну конструкцию
    qbdsIT = qbdsIJT.addDataSource(tableNum(InventLocation));
    qbdsIT.fetchMode(QueryFetchMode::One2One);
    qbdsIT.joinMode(JoinMode::ExistsJoin);
    qbdsIT.relations(false);
    // это на самом деле relation
    qbr = qbdsIT.addRange(fieldNum(InventLocation, InventLocationId));
    qbr.value(strFmt('(%1.%2 = %4.%5) || (%1.%3 = %4.%5)',
        qbdsIJT.name(), fieldStr(InventJournalTable, InventLocationId), fieldStr(InventJournalTable, InventLocationIdTo),
        qbdsIT.name(), fieldStr(InventLocation, InventLocationId)) );
    // прочие условия (на справочник складов)
чё-то стрёмно такой workaruond применять.
опять же скорее всего, нам не все условия показали, а только самое тривиальное.

и если условия в ТЗ будут углублены и расширены (а они будут углублены)
то такой маневр будет оооочень сильно мешать.
__________________
полезное на axForum, github, vk, coub.
Старый 19.06.2017, 22:44   #7  
dim-gin is offline
dim-gin
Участник
 
41 / 30 (2) +++
Регистрация: 15.04.2014
Адрес: СПб
2 mazzy:
Да, это не самое элегантное решение. Но разве исходные 2 exists join'а с OR намного проще в выполнении для БД? Или Вы подразумеваете другой смысл под словом "мешать"?

Последний раз редактировалось dim-gin; 19.06.2017 в 22:45. Причина: опечатка
Старый 19.06.2017, 23:00   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
для БД не проще.
мешать будет человеку.

если сейчас условие упаковать в один existJoin, то с появлением новых условий на склады, условие придется делать все более навороченным и сильно непонятным и для программиста, и для пользователя.

пользователь появляется поскольку часто готовый query может оказаться в стандартном диалоге, где пользователь может его подправить. даже опытный пользователь повесится. придется делать этот range::Locked. а затем придумывать обходные пути чтобы таки как-то разрешить.

да, из кода видно, что в данном случае разработчики не парятся с критериями, а используют диалог с единственным значением для фильтра в каждом range. и хорошо, если это значение можно подставить из выпадающего списка )))

но рано или поздно они могут захотеть таки перейти на полноценные критерии вместо единственного значения.

этот workaround сделает любое расширение условия по складам очень нетривиальным и сложным.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: dim-gin (1).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
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, время: 10:41.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.