Показать сообщение отдельно
Старый 30.03.2010, 17:21   #11  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от _scorp_ Посмотреть сообщение
X++:
    UserConnection  con = new UserConnection();
...
        info(resultSet.getString(1));
...
Цитата:
Сообщение от Alexius Посмотреть сообщение
Попробуйте через класс Connection для соединения с текущей БД Аксапты:
Зачем же вы человеку плохое советуете?

Цитата:
Сообщение от kalex_a Посмотреть сообщение
Здравствуйте, подскажите пожалуйста, как сделать такой запрос в Axapta? и что использовать лучьше View(это было бы лучьше), Query или какой нибудь while select, просто не знаю, знаю как простые запросы делать, а такие .
Во-первых, обязательно прочитайте про режимы кэширования таблиц в Аксапте. Из-за режимов кэширования в Аксапте зачастую писать вложенные И простые запросы выгоднее, нежели один навороченный супер-запрос с кучей join'ов.
Во-вторых, среди программистов Аксапты не принято сокращать суффиксы (типа Trans) и префиксы (типа Vend). Прочитайте хелп для разработчика на предмет соглашений по наименованию объектов.
В-третьих, обязательно старайтесь вникнуть в предметную область. Сумма по полю AmountCur не имеет никакого смысла, если вы не накладываете никаких условий на валюту. Сейчас ваш запрос суммирует рубли, тугрики, евро, доллары и т.д. и проверяет получившуюся сумму на ноль. Смысла в этом условии - никакого.
В-четвертых, обязательно поймите смысл полей. Так вы делаете выборку с условием (VTr.closed='') и добавляете having sum(VTr.AmountCur)=0. Вообще говоря, в Аксапте если проводка НЕ закрыта, то ее надо анализировать и выбирать даже если сумма оплат с накладными равна 0. Такова логика Аксапты. Система перестает анализировать только Закрытые записи. Ваш Having одним махом нарушает логику работы стандартного функционала и превращает Аксапту в 1С
В-пятых, поймите соотношение таблиц и данных в таблицах. Так в Аксапте для открытых проводок по клиентам и поставщикам есть специальная таблица VendTransOpen, которая содержит только открытую часть из проводок по поставщикам.
В-шестых, таблица RContractTable содержит договоры как с поставщиками, так и с клиентами. Поэтому делать выборку из RContractTable без указания типа нельзя!!! Ведь у вас могут быть клиенты и поставщики с одинаковым кодом.
В-седьмых, поскольку вы не разбирались с предметной областью и с таблицами, вы указали сортировку по полю, по которому нет индекса. В итоге ваша супер-оптимизация-в-один-запрос идет лесом из-за того, что сортировка будет происходить в temp-базе данных SQL-сервера.
В-восьмых, вы неправильно связали таблицу RContractTable и VendTrans - не все поля указали.
В-девятых, поле Closed имеет тип Date

Поэтому правильный ответ на ваш вопрос - ни в коем случае не нужно делать так как вы хотите. Если вам дал задачу некий "постановщик" или "аналитик" - четвертуйте его. Можно медленно.

Постараемся понять что же вы делаете и сформулировать на нормальном человеческом языке:
Вы хотите получить список различных поставщиков (код, наименование) с кодами их договоров по которым есть хоть какие-то незакрытые суммы (список должен быть отсортирован по коду договора)
При реверс-инжиниринге вашего запроса возникает неопределенность - каким образом вы трактуете незакрытость. Стандартная Аксапта использует только признак закрытости - этот признак устанавливается ПОСЛЕ операции сопоставления (никаких проверок сумм на ноль). Вы зачем-то вводите условие, что сумма должна быть ненулевой, что тут же отменяет функционал сопоставления (и тут же вносит кучу багов с курсовыми разницами и разными валютами). Поэтому, скорее всего, условие в Having - это неправильное условие (Я надеюсь, что вы не хотели сломать Аксапту сознательно).

Поэтому запрос, аналогичный вашему, в Аксапте должен быть таким:

X++:
static void Job11(Args _args)
{
    RContractTable  RContractTable;
    VendTrans       VendTrans;
    VendTransOpen   VendTransOpen;
    VendTable       VendTable;


    while select RContractTable
        index ContractTypeCodeAccountIdx
        where RContractTable.RContractPartnerType == RContractPartnerType::Vend
    {
        select firstonly VendTrans
            where VendTrans.RContractAccount == RContractTable.RContractAccount
        exists join VendTransOpen
            where VendTrans.AccountNum == VendTransOpen.AccountNum
               && VendTrans.RecId == VendTransOpen.RefRecId;

        if( !VendTrans )
            continue;

        VendTable = VendTable::find(RContractTable.RContractAccount);
        info(strfmt("%1 %2 %3 %4", VendTable.AccountNum, VendTable.Name,RContractTable.RContractAccount,RContractTable.RContractCode));
    }

}
Несмотря на то, что тут два вложенных запроса, этот запрос будет более оптимальным, чем ваш.

Пооптимизируем:
Если честно, то я не вижу абсолютно никакого смысла сортировать результаты выдачи по КОДУ договора. Если убрать требование сортировки по коду и в цикле договоры не нужны, то запрос может быть гораздо простым и вполне Аксаптовским:
X++:
static void Job12(Args _args)
{
    //RContractTable  RContractTable; // Раскоментируйте, если внутри цикла нужны данные из договора
    VendTrans       VendTrans;
    VendTransOpen   VendTransOpen;
    VendTable       VendTable;


    while select count(recid) from VendTrans
        group by AccountNum, RContractAccount, RContractCode
    exists join VendTransOpen
        where VendTrans.AccountNum == VendTransOpen.AccountNum
           && VendTrans.RecId == VendTransOpen.RefRecId
    {
        //RContractTable = RContractTable::find(RContractPartnerType::Vend, VendTrans.RContractCode, VendTrans.RContractAccount);
        VendTable = VendTable::find(VendTrans.AccountNum);
        info(strfmt("%1 %2 %3 %4", VendTable.AccountNum, VendTable.Name,VendTrans.RContractAccount,VendTrans.RContractCode));
    }

}
Но вообще говоря, в проводках Аксапты есть и суммы, и признак закрытости. Поэтому, если подумать и посмотреть в метод open таблицы VendTrans (а также если внутри цикла не нужны данные из VendTransOpen), то запрос становится вообще тривиальным:
X++:
static void Job14(Args _args)
{
    VendTrans       VendTrans;
    VendTable       VendTable;

    while select sum(AmountMST), sum(SettleAmountMST) from VendTrans
        group by AccountNum, RContractAccount, RContractCode
        where VendTrans.amountCur != VendTrans.settleAmountCur // условие взято из метода Open() таблицы VendTrans
    {
        VendTable = VendTable::find(VendTrans.AccountNum);
        info(strfmt("%1 %2 %3 %4", VendTable.AccountNum, VendTable.Name,VendTrans.RContractAccount,VendTrans.RContractCode));
    }

}
И тут можно подумать над тем, сравнивать ли поле Closed c datenull() или все-таки пользоваться условием на неравенство сумм из метода open()... Что будет оптимальнее, надо смотреть в базу. Более правильным, с точки зрения Аксапты, является условие из метода open().


В общем, прежде всего - изучите предметную область.
И проштудируйте про кэширование.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: alex55 (1), AP-1055D (1).