У меня есть две таблицы:
INVOICES
ID | DISCOUNT_PRC
1 | NULL
2 | 0.10
3 | 0.70
...
INVOICE_ITEMS
ID | INVOICE_ID | PRICE | ALT_PRICE
1 | 1 | 100 | 0
2 | 1 | 200 | 150
3 | 2 | 400 | 300
4 | 2 | 200 | 0
5 | 2 | 100 | NULL
6 | 3 | 200 | 40
7 | 3 | 100 | NULL
...
ПРИМЕЧАНИЕ. База данных используется другим приложением, мне не разрешено изменять нули на значения NULL
или наоборот.
Мне нужно вывести сумму товаров для каждого счета-фактуры, при этом PRICE
каждого товара умножается на скидку (1 - DISCOUNT_PRC)
, за исключением случаев, когда ALT_PRICE
не равно NULL
и больше нуля.В этом случае просто возьмите ALT_PRICE
.Итак, желаемый результат будет выглядеть так:
INVOICES
ID | OVERALL_PRICE
1 | 250 (100*1) + (150)
2 | 570 (300) + (200*0.9) + (100*0.9)
3 | 70 (40) + (100*0.3)
Что у меня есть до сих пор:
select I.ID,
case when ISNULL( IT.ALT_PRICE, 0) > 0
then IT.ALT_PRICE
else IT.PRICE * (1 - ISNULL( I.DISCOUNT_PRC, 0))
end AS OVERALL_PRICE
from INVOICES I
join INVOICE_ITEMS IT on IT.INVOICE_ID = I.ID
Результат
ID OVERALL_PRICE
1 100
1 150
2 300
2 180
2 90
3 40
3 30
Результат действителен длякаждый элемент, теперь мне нужно SUM
их в один ряд для каждого счета.Я пробовал это с использованием LEFT JOIN
, а затем с OUTER_APPLY
:
select I.ID, items.OVERALL_PRICE FROM INVOICES I
OUTER APPLY ( select sum (
case when ISNULL( IT.ALT_PRICE, 0) > 0
then IT.ALT_PRICE
else IT.PRICE * (1 - ISNULL( I.DISCOUNT_PRC, 0))
end) AS OVERALL_PRICE
from INVOICE_ITEMS IT
where IT.INVOICE_ID = I.ID
group by IT.INVOICE_ID ) as items
Но я получаю ту же ошибку:
Multiple columns are specified in an aggregated expression containing an outer reference. If an expression being aggregated contains an outer reference, then that outer reference must be the only column referenced in the expression.
РЕДАКТИРОВАТЬ: Я также хотел бы избежать использования SUM
(или любого другого агрегированного выражения) в столбцах моего основного запроса, поскольку для этого потребуется сгруппировать все остальные столбцы.Фактическая таблица содержит более 50 столбцов и некоторые другие подзапросы, поэтому я хочу этого избежать.
РЕДАКТИРОВАТЬ 2: Хорошо, я провел сравнительный анализ с решениями из B3S (объединение в подзапросе), iSR5 (над) и Гордон Линофф (подать заявку).Я вставил счета-фактуры 50 КБ и элементы счета-фактуры 500 КБ и использовал MSSQL STATISTICS
, он должен показывать достаточно приличные результаты в зависимости от размера базы данных.Вот результаты:
Join within subquery:
- CPU time = 1170 ms, elapsed time = 335 ms.
- CPU time = 1202 ms, elapsed time = 344 ms.
- CPU time = 1153 ms, elapsed time = 348 ms.
OVER:
- CPU time = 3089 ms, elapsed time = 1361 ms.
- CPU time = 3010 ms, elapsed time = 1075 ms.
- CPU time = 3010 ms, elapsed time = 1070 ms.
APPLY:
- CPU time = 2496 ms, elapsed time = 2320 ms.
- CPU time = 2433 ms, elapsed time = 2171 ms.
- CPU time = 2496 ms, elapsed time = 2179 ms.
Заключение: Я ожидал, что объединение в подзапросе будет оптимизировано SQL, но я все еще ожидал увидеть лучшие результаты с двумя другимипредложения.Это довольно неожиданно для меня, но я должен отдать должное (и принятый ответ) B3S.Я был уверен, что внутреннее соединение нанесет удар по спектаклю, я не стал его пробовать.В любом случае, не стесняйтесь присоединиться к внешней таблице из подзапроса - если необходимо, конечно.