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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 31.08.2008, 13:04   #1  
koraman is offline
koraman
Участник
 
41 / 11 (1) +
Регистрация: 12.02.2008
Адрес: Казань
outer join и агрегаты
Подскажите, пожалуйста, возможно ли в X++ использовать outer join с агрегатами? А то синтаксис языка таков, что будто это возможно... и было бы, конечно, очень удобно... И если возможно, как этого добиться? Пытаюсь сделать что-то наподобие следующего:
X++:
while select custTable
    outer join AccountNum, sum(AmountMST) from custTrans
        group by AccountNum
        where custTrans.AccountNum == custTable.AccountNum
{
}
Он же мне выводит пустоту...
__________________
I believe!
Старый 31.08.2008, 13:53   #2  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
попробуйте
X++:
while select max(recID) from custTable outer join ...
Старый 01.09.2008, 09:05   #3  
koraman is offline
koraman
Участник
 
41 / 11 (1) +
Регистрация: 12.02.2008
Адрес: Казань
К сожалению, не получается...
Перепробовал много способов - видимо, такой возможности всё-таки нет... жаль...
__________________
I believe!
Старый 01.09.2008, 09:15   #4  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
а что на сервер уходит? вообще непонятно зачем так делать, потому, что x + NULL = NULL
Старый 01.09.2008, 09:26   #5  
NNB is offline
NNB
Участник
 
103 / 12 (1) ++
Регистрация: 31.08.2006
Я использовал промежуточные таблицы
Старый 01.09.2008, 10:22   #6  
koraman is offline
koraman
Участник
 
41 / 11 (1) +
Регистрация: 12.02.2008
Адрес: Казань
Цитата:
Сообщение от belugin Посмотреть сообщение
а что на сервер уходит? вообще непонятно зачем так делать, потому, что x + NULL = NULL
Как посмотреть, что уходит на сервер?
Это было бы удобно, например, когда для каждого клиента надо вывести суммарный оборот.

Цитата:
Сообщение от NNB Посмотреть сообщение
Я использовал промежуточные таблицы
Аналогично.
__________________
I believe!
Старый 01.09.2008, 10:33   #7  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
А что конкретно у Вас не получается? У меня вот этот job отрабатывает нормально
X++:
static void Job(Args _args)
{
    Custtable custTable;
    Custtrans custTrans;
    ;
    while select custTable
    outer join sum(AmountMST) from custTrans
        group by AccountNum
        where custTrans.AccountNum == custTable.AccountNum
    {
        print strfmt("%1 %2", custTrans.AccountNum, custtrans.AmountMST);
    }
    pause;
}
Старый 01.09.2008, 10:35   #8  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Папробуйте вот так:
X++:
while select TableId from custTable
    outer join sum(AmountMST) from custTrans
        group by AccountNum
        where custTrans.AccountNum == custTable.AccountNum
{
}
Таким образом у вас выберутся суммы сгруппированные по коду клиента
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 01.09.2008, 11:57   #9  
koraman is offline
koraman
Участник
 
41 / 11 (1) +
Регистрация: 12.02.2008
Адрес: Казань
Это какая-то мистика! Я, конечно, в аксапте новичок... Она всегда такая непредсказуемая?
Сегодня после поста _scorp_ у меня заработал скрипт, который я выкладывал в начале!
Цель же - немножко посложнее. Мне необходимо вывести для каждого клиента список договоров с указанием суммарного оборота по каждому.
Я создал тестовую формочку с одним единственным гридом, который цепляется к временной табличке, которая перед отображением заполняется своим методом fill().

Итак. Проблема.

Объявление переменных:
X++:
    CustTable custTable;
    ContactPerson contactPerson;
    CustGroup custGroup;
    RContractTable contractTable;
    RContractTypes contractTypes;
    CustTrans custTrans;
    ;
Шаг 1:
X++:
    while select custTable order by AccountNum
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
    {
        this.CustInfo = custTable.AccountNum + ", " + contactPerson.Name;
        this.insert();
    } // end while
Здесь всё нормально. Выбирается, джойнится, отображается.

Шаг 2:
X++:
    while select custTable order by AccountNum
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
        outer join custGroup where
            (custGroup.dataAreaId == contactPerson.dataAreaId || custGroup.dataAreaId != contactPerson.dataAreaId) &&
            custTable.CustGroup == custGroup.CustGroup
    {
        this.CustInfo = custTable.AccountNum + ", " + contactPerson.Name;
        this.CustGroupName = custGroup.Name;
        this.insert();
    } // end while
Добавили ещё один джоин, стали отображать ещё один столбец - и появилась первая проблема! Почему-то у нескольких записей перестало отображаться название группы клиентов CustGroup.Name! Всё вроде бы нормально... В CustTable группа указана, в CustGroup она существует, для многих строк она в гриде отображается, но для некоторых не отображается. Почему?

Шаг 3:
X++:
    while select custTable order by AccountNum
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
        outer join custGroup where
            (custGroup.dataAreaId == contactPerson.dataAreaId || custGroup.dataAreaId != contactPerson.dataAreaId) &&
            custTable.CustGroup == custGroup.CustGroup
        outer join contractTable where
            (contractTable.dataAreaId == custGroup.dataAreaId || contractTable.dataAreaId != custGroup.dataAreaId) &&
            contractTable.RContractPartnerCode == custTable.AccountNum &&
            contractTable.RContractPartnerType == RContractPartnerType::Cust
        outer join contractTypes where
            (contractTypes.dataAreaId == contractTable.dataAreaId || contractTypes.dataAreaId != contractTable.dataAreaId) &&
            contractTypes.ContractCode == contractTable.RContractCode
    {
        this.CustInfo = custTable.AccountNum + ", " + contactPerson.Name;
        this.CustGroupName = custGroup.Name;
        this.ContractRegNo = contractTable.RContractAccount;
        this.ContractNo = contractTable.RContractNumber;
        this.ContractGroupName = contractTypes.ContractCodeName;
        this.insert();
    } // end while
Здесь мы добавили уже два джойна, но осложнений больше нет - всё хорошо и аккуратно... за исключением групп, конечно...

Шаг 4:
X++:
    while select custTable order by AccountNum
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
        outer join custGroup where
            (custGroup.dataAreaId == contactPerson.dataAreaId || custGroup.dataAreaId != contactPerson.dataAreaId) &&
            custTable.CustGroup == custGroup.CustGroup
        outer join contractTable where
            (contractTable.dataAreaId == custGroup.dataAreaId || contractTable.dataAreaId != custGroup.dataAreaId) &&
            contractTable.RContractPartnerCode == custTable.AccountNum &&
            contractTable.RContractPartnerType == RContractPartnerType::Cust
        outer join contractTypes where
            (contractTypes.dataAreaId == contractTable.dataAreaId || contractTypes.dataAreaId != contractTable.dataAreaId) &&
            contractTypes.ContractCode == contractTable.RContractCode
        outer join AccountNum, sum(AmountMST) from custTrans group by AccountNum where
            (custTrans.dataAreaId == contractTypes.dataAreaId || custTrans.dataAreaId != contractTypes.dataAreaId) &&
            custTrans.RContractAccount == contractTable.RContractAccount &&
            custTrans.RContractCode == contractTable.RContractCode
    {
        this.CustInfo = custTable.AccountNum + ", " + contactPerson.Name;
        this.CustGroupName = custGroup.Name;
        this.ContractRegNo = contractTable.RContractAccount;
        this.ContractNo = contractTable.RContractNumber;
        this.ContractGroupName = contractTypes.ContractCodeName;
        this.Amount = custTrans.AmountMST;
        this.insert();
    } // end while
Вот здесь уже всё валится. И по-разному. Вчера это был просто пустой грид, а сегодня уже сообщение типа "Невозможно выбрать запись в CustTable. База данных SQL обнаружила ашипку.".

Хотя и реализовал задачку другим путём, мозги всё равно стремятся сломаться об эти две проблемы...
__________________
I believe!
Старый 01.09.2008, 12:01   #10  
koraman is offline
koraman
Участник
 
41 / 11 (1) +
Регистрация: 12.02.2008
Адрес: Казань
Ой, база данных SQL обнаружила ошибку потому, что я забыл убрать order by в while select custTable. То есть итоговый запрос выглядит так:
X++:
    while select custTable
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
        outer join custGroup where
            (custGroup.dataAreaId == contactPerson.dataAreaId || custGroup.dataAreaId != contactPerson.dataAreaId) &&
            custTable.CustGroup == custGroup.CustGroup
        outer join contractTable where
            (contractTable.dataAreaId == custGroup.dataAreaId || contractTable.dataAreaId != custGroup.dataAreaId) &&
            contractTable.RContractPartnerCode == custTable.AccountNum &&
            contractTable.RContractPartnerType == RContractPartnerType::Cust
        outer join contractTypes where
            (contractTypes.dataAreaId == contractTable.dataAreaId || contractTypes.dataAreaId != contractTable.dataAreaId) &&
            contractTypes.ContractCode == contractTable.RContractCode
        outer join RContractAccount, RContractCode, sum(AmountMST) from custTrans group by RContractAccount, RContractCode where
            (custTrans.dataAreaId == contractTypes.dataAreaId || custTrans.dataAreaId != contractTypes.dataAreaId) &&
            custTrans.RContractAccount == contractTable.RContractAccount &&
            custTrans.RContractCode == contractTable.RContractCode
    {
        this.CustInfo = custTable.AccountNum + ", " + contactPerson.Name;
        this.CustGroupName = custGroup.Name;
        this.ContractRegNo = contractTable.RContractAccount;
        this.ContractNo = contractTable.RContractNumber;
        this.ContractGroupName = contractTypes.ContractCodeName;
        this.Amount = custTrans.AmountMST;
        this.insert();
    } // end while
Вот. Но тем не менее грид оказывается таким же пустым... и с группами всё так же...

Да, кстати. В таблице CustTrans нет записей, соответствующих записям из RContractTable, но ведь используется OUTER join.
__________________
I believe!

Последний раз редактировалось koraman; 01.09.2008 в 12:13.
Старый 01.09.2008, 12:11   #11  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от koraman Посмотреть сообщение
Это какая-то мистика!
Барабашки нет.

Цитата:
Сообщение от koraman Посмотреть сообщение
Шаг 2:
X++:
    while select custTable order by AccountNum
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
        outer join custGroup where
            (custGroup.dataAreaId == contactPerson.dataAreaId || custGroup.dataAreaId != contactPerson.dataAreaId) &&
            custTable.CustGroup == custGroup.CustGroup
    {
        this.CustInfo = custTable.AccountNum + ", " + contactPerson.Name;
        this.CustGroupName = custGroup.Name;
        this.insert();
    } // end while
Очень странное условие в запросе.

Цитата:
Сообщение от koraman Посмотреть сообщение
Добавили ещё один джоин, стали отображать ещё один столбец - и появилась первая проблема! Почему-то у нескольких записей перестало отображаться название группы клиентов CustGroup.Name!
Читайте про outer join на этом форуме.
Аксапта плохо переваривает несколько outer join'ов.

Почему? Потому что разыменование в Аксапте делается совершенно другим способом. Вы привыкли к LEFT JOIN'ам и считаете, что это быстро. Нет, в Аксапте очень много зявязано на кэширование записей (читайте про кэширование в транзакции, вне транзакции, а также кэширование таблиц).

Суть Аксапта-подхода:
1. Естественные коды (коды должны быть такими, что легко читаются и понимаются человеком). В результате потребность в разыменовании резко снижается. См. стандартные формы и отчеты. См. неоднократные обсуждения на этом форуме и здесь http://axapta.mazzy.ru/lib/autonumber/
2. Использовать простые запросы с вложенными простыми и КЭШИРУЕМЫМИ запросами.

Если вам всетаки нужно разыменование, то лучше написать сложенный запрос к CustGroup и при этом убедится что CustGroup кэшируемая таблица
X++:
    while select custTable order by AccountNum
        outer join contactPerson where
            custTable.ContactPersonId == contactPerson.ContactPersonId
    {
        custGroup == custGroup::find(custTable.CustGroup);
    }
Почему так? Потому что внешний запрос будет гораздо проще и поэтому будет быстрее возвращаться. Возвращаемый массив данных будет меньше (что чертовски важно для тонких каналов)

А вот внутренний запрос будет выполняться на SQL только в первый раз за пользовательскую сессию. как правило, результаты будет браться из кэша КЛИЕНТА.

Вывод - не усложняйте запросы. В Аксапте не всегда вложенные запросы плохо.
Детально разберитесь с кэшированием записей.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: koraman (1).
Старый 01.09.2008, 12:12   #12  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
При выборе суммы по полю необходимо указывать группировку полей по всем дата сорсам которые участвуют в запросе.
Вообще запрос получился какой то громоздкий, я бы точно вынес в отдельный select нахождение суммы.

P.S. mazzy прав.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем

Последний раз редактировалось lev; 01.09.2008 в 12:14. Причина: P.S.
Старый 01.09.2008, 12:13   #13  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от koraman Посмотреть сообщение
То есть итоговый запрос выглядит так:
Ужас.
__________________
полезное на axForum, github, vk, coub.
Старый 01.09.2008, 12:20   #14  
koraman is offline
koraman
Участник
 
41 / 11 (1) +
Регистрация: 12.02.2008
Адрес: Казань
Значит, не всё так просто... что ж... будем читать.
Спасибо за разъяснения!
__________________
I believe!
Старый 01.09.2008, 12:52   #16  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
можно попробовать сделать сгруппированное view и его уже аутер джоинить
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Двойной Outer Join в Query LTA DAX: Программирование 2 21.01.2020 09:28
Несколько outer join в запросе _scorp_ DAX: Программирование 2 11.04.2008 10:56
Данные в Grid из таблиц, связанных по Outer Join cherv DAX: Программирование 2 17.02.2007 01:36
2 и более OUTER JOIN к одному паренту Ronin DAX: Программирование 21 19.12.2005 13:42
outer join для трех таблиц r25 DAX: Программирование 4 29.04.2004 15:42

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

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

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