#sql #tsql #case
#sql #tsql #случай
Вопрос:
У меня есть запрос, который вычисляет 3 суммы и затем классифицирует их по диапазонам дней просрочки платежа.
Однако иногда для некоторых диапазонов нет данных, поэтому запрос возвращает менее 3 строк.
Как заставить запрос всегда возвращать 3 строки, даже если нет данных для определенного DaysLate
диапазона? В этом случае Suma
и Docs
должны содержать нули.
SELECT MIN(b.Range) Nazwa, SUM(b.Remaining) Suma, COUNT(*) Docs
FROM (
SELECT
CASE
WHEN a.DaysLate BETWEEN 1 AND 14 THEN 'Late 1 to 14 days'
WHEN a.DaysLate BETWEEN 15 AND 30 THEN 'Late 15 to 30 day'
ELSE 'Late over 30 days'
END AS Range,
CASE
WHEN a.DaysLate BETWEEN 1 AND 14 THEN 1
WHEN a.DaysLate BETWEEN 15 AND 30 THEN 2
ELSE 3
END AS Order,
Remaining, DaysLate
FROM (
SELECT DATEDIFF(dd, PaymentDate, GETDATE()) DaysLate, (WN - MA) Remaining
FROM dbo.MyData
WHERE DATEDIFF(dd, PaymentDate, GETDATE()) > 0 AND KOD_ID = @KOD_ID
) a
) b
GROUP BY b.Order
ORDER BY b.Order ASC
Ответ №1:
Вам нужен LEFT JOIN
, но вы также можете упростить запрос с помощью APPLY
:
SELECT ranges.range, SUM(v.Remaining) as Suma,
COUNT(*) as Docs
FROM (VALUES ('Late 1 to 14 days', 1),
('Late 15 to 30 day', 2),
('Late over 30 days', 3)
) ranges(range, ord) LEFT JOIN
(dbo.MyData d CROSS APPLY
(VALUES (DATEDIFF(day, d.PaymentDate, GETDATE()),
WN - MA
)
) v(DaysLate, Remaining) CROSS APPLY
(VALUES (CASE WHEN v.DaysLate BETWEEN 1 AND 14
THEN 'Late 1 to 14 days'
WHEN v.DaysLate BETWEEN 15 AND 30
THEN 'Late 15 to 30 day'
ELSE 'Late over 30 days'
END)
) v1(range)
)
ON v1.range = ranges.range
WHERE v.DaysLate > 0 AND
KOD_ID = @KOD_ID
GROUP BY v.range, v.ord
ORDER BY v.ord;