#sql #oracle
Вопрос:
Мне нужно создать запрос oracle, который приведет к следующему отчету
Name AccountId DistributorBalance DealerBalance StoreBalance
Я должен извлечь данные из трех связанных таблиц, которые:
- Партнеры
- счета партнеров
- счета
Партнеры повторят три раза, как самостоятельное соединение, и каждое соединение из трех самостоятельных соединений partner
должно присоединиться partneraccounts
к таблице; также таблица accounts
должна присоединиться partneraccounts
. Я создаю этот подзапрос и получаю следующую ошибку:
Select dis.name,DistributorBalace,DealerBalance,StoreBalance From
(
select dis.name,disa.credit-disa.debit DistributorBalace
from partners dis join
partneraccounts disp on dis.partnerid=disp.partnerid
join accounts disa on disa.accountid=disp.accountid
where dis.identitytypeid=19
union all
select de.name, dea.credit-dea.debit DealerBalance from partners de join
partneraccounts dep on dep.partnerid=de.partnerid
join accounts dea on dea.accountid=dep.accountid
where de.identitytypeid=7
union all
select ag.name,aga.credit-aga.debit StoreBalance from partners ag join
partneraccounts apa on apa.partnerid=ag.partnerid
join accounts aga on aga.accountid=apa.accountid
where ag.identitytypeid=8 ) A
Error
ORA-00904: "STOREBALANCE": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error at Line: 1 Column: 49
Комментарии:
1. попробуйте ввести
as
ключевоеselect ag.name,aga.credit-aga.debit as StoreBalance
слово и включить его во все запросы.2. я не понял тебя, братан, как поставить это на все запросы, мне нужны разные результаты данных по трем запросам
3. поскольку это объединение, все столбцы из всех запросов должны быть одного типа. удалите DistributorBalace , DealerBalance , StoreBalance из ваших запросов, а затем запустите его
4. Вы дали имя результату
A
подзапроса . Т. е. вы можете только выбратьA.name
и т. Д.5. Одни и те же таблицы во всех таблицах с ОБЪЕДИНЕНИЕМ. Разве вы не можете просто сделать один-единственный ВЫБОР?
Ответ №1:
Запрос ОБЪЕДИНЕНИЯ имеет проекцию самого верхнего подзапроса. В вашем случае это так name, DistributorBalance
(обратите внимание на исправление опечатки). В этой проекции нет столбца, вызываемого StoreBalance
, следовательно, ошибка.
Вам нужны все три баланса в выходных данных, поэтому вам нужны подзапросы, которые возвращают все три. Обратите внимание , что указанный вами вывод также требуется accountid
, поэтому включите и это. Что-то вроде этого:
select a.name
,a.accountid
,a.DistributorBalance
,a.DealerBalance
,a.StoreBalance
from (
select dis.name
,disp.accountid
,disa.credit - disa.debit as DistributorBalance
,cast(null as number) as DealerBalance
,cast(null as number) as StoreBalance
from partners dis
join partneraccounts disp on dis.partnerid = disp.partnerid
join accounts disa on disa.accountid = disp.accountid
where dis.identitytypeid = 19
union all
select de.name
dea.accountid
,cast(null as number) as DistributorBalance
,dea.credit - dea.debit as DealerBalance
,cast(null as number) as StoreBalance
from partners de
join partneraccounts dep on dep.partnerid = de.partnerid
join accounts dea on dea.accountid = dep.accountid
where de.identitytypeid = 7
union all
select ag.name
,aga.accountid
,cast(null as number) as DistributorBalance
,cast(null as number) as DealerBalance
,aga.credit - aga.debit as StoreBalance
from partners ag
join partneraccounts apa on apa.partnerid = ag.partnerid
join accounts aga on aga.accountid = apa.accountid
where ag.identitytypeid = 8
) a
Честно говоря, запрос объединения, подобный этому, может быть не самым эффективным способом выполнения задач, в зависимости от характеристик данных (объем, распределение и т. Д.). Я оставляю запрос, как указано выше, потому что он отвечает на поставленный вопрос, но если бы время выполнения оказалось проблемой, я бы извлек соединения из трех таблиц в один подзапрос С предложением и заменил подзапросы ОБЪЕДИНЕНИЯ на выбор. Или просто используйте три выписки по ДЕЛУ для разных балансов. Этот рефакторинг оставлен в качестве упражнения для читателя 🙂
Комментарии:
1. Спасибо, братан, теперь ошибка устранена , но, как вы указали выше, результат не отвечает требуемым данным, должно отображаться только поле имени таблицы дистрибьютора bcz, в то время как результат выдает все три таблицы
Ответ №2:
Я думаю, что это было бы намного проще с условной агрегацией:
select p.name,
sum(case when p.identitytypeid = 19 then a.credit - a.debit end) as DistributorBalance,
sum(case when p.identitytypeid = 7 then a.credit - a.debit end) as DealerBalance,
sum(case when p.identitytypeid = 8 then a.credit - a.debit end) as StoreBalance
from partners p join
partneraccounts pa
on p.partnerid = pa.partnerid join
accounts a
on a.accountid = pa.accountid
group by p.name;