31.08.2008, 13:04 | #1 |
Участник
|
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 |
Участник
|
попробуйте
X++: while select max(recID) from custTable outer join ... |
|
01.09.2008, 09:05 | #3 |
Участник
|
К сожалению, не получается...
Перепробовал много способов - видимо, такой возможности всё-таки нет... жаль...
__________________
I believe! |
|
01.09.2008, 09:15 | #4 |
Участник
|
а что на сервер уходит? вообще непонятно зачем так делать, потому, что x + NULL = NULL
|
|
01.09.2008, 09:26 | #5 |
Участник
|
Я использовал промежуточные таблицы
|
|
01.09.2008, 10:22 | #6 |
Участник
|
Цитата:
Это было бы удобно, например, когда для каждого клиента надо вывести суммарный оборот. Аналогично.
__________________
I believe! |
|
01.09.2008, 10:33 | #7 |
Участник
|
А что конкретно у Вас не получается? У меня вот этот 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 |
Ищущий знания...
|
Папробуйте вот так:
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 |
Участник
|
Это какая-то мистика! Я, конечно, в аксапте новичок... Она всегда такая непредсказуемая?
Сегодня после поста _scorp_ у меня заработал скрипт, который я выкладывал в начале! Цель же - немножко посложнее. Мне необходимо вывести для каждого клиента список договоров с указанием суммарного оборота по каждому. Я создал тестовую формочку с одним единственным гридом, который цепляется к временной табличке, которая перед отображением заполняется своим методом fill(). Итак. Проблема. Объявление переменных: X++: CustTable custTable; ContactPerson contactPerson; CustGroup custGroup; RContractTable contractTable; RContractTypes contractTypes; CustTrans custTrans; ; 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 Шаг 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 Хотя и реализовал задачку другим путём, мозги всё равно стремятся сломаться об эти две проблемы...
__________________
I believe! |
|
01.09.2008, 12:01 | #10 |
Участник
|
Ой, база данных 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 |
Участник
|
Барабашки нет.
Цитата:
Сообщение от 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 Цитата:
Аксапта плохо переваривает несколько 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 только в первый раз за пользовательскую сессию. как правило, результаты будет браться из кэша КЛИЕНТА. Вывод - не усложняйте запросы. В Аксапте не всегда вложенные запросы плохо. Детально разберитесь с кэшированием записей. |
|
|
За это сообщение автора поблагодарили: koraman (1). |
01.09.2008, 12:12 | #12 |
Ищущий знания...
|
При выборе суммы по полю необходимо указывать группировку полей по всем дата сорсам которые участвуют в запросе.
Вообще запрос получился какой то громоздкий, я бы точно вынес в отдельный select нахождение суммы. P.S. mazzy прав.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем Последний раз редактировалось lev; 01.09.2008 в 12:14. Причина: P.S. |
|
01.09.2008, 12:13 | #13 |
Участник
|
|
|
01.09.2008, 12:20 | #14 |
Участник
|
Значит, не всё так просто... что ж... будем читать.
Спасибо за разъяснения!
__________________
I believe! |
|
01.09.2008, 12:52 | #16 |
Участник
|
можно попробовать сделать сгруппированное view и его уже аутер джоинить
|
|