Herschrijf eerst uw vraag. Gebruik weergaven of algemene tabeluitdrukkingen om te voorkomen dat u zich drie keer herhaalt voor uw SELECT
, GROUP BY
, ORDER BY
clausules. Uw vraag wordt:
WITH data AS (
SELECT(CASE WHEN time_dtm > SYSDATE -1 THEN '0-1 day'
WHEN time_dtm > SYSDATE -2 AND
time_dtm < SYSDATE -1 THEN '1-2 days'
WHEN time_dtm > SYSDATE -3 AND
time_dtm < SYSDATE -2 THEN '2-3 days'
WHEN time_dtm > SYSDATE -4 AND
time_dtm < SYSDATE -3 THEN '3-4 days'
WHEN time_dtm > SYSDATE -5 AND
time_dtm < SYSDATE -4 THEN 'Closed'
END) AS Age
FROM table_1
WHERE id IN (1,2,3)
)
SELECT Age, COUNT(*)
FROM data
GROUP BY Age
ORDER BY Age
Om er zeker van te zijn dat een van uw gewenste groepen beschikbaar zal zijn in het resultaat, heeft u veel opties.
Je zou UNION ALL
. kunnen gebruiken :
WITH data AS (
SELECT(CASE WHEN time_dtm > SYSDATE -1 THEN '0-1 day'
WHEN time_dtm > SYSDATE -2 AND
time_dtm < SYSDATE -1 THEN '1-2 days'
WHEN time_dtm > SYSDATE -3 AND
time_dtm < SYSDATE -2 THEN '2-3 days'
WHEN time_dtm > SYSDATE -4 AND
time_dtm < SYSDATE -3 THEN '3-4 days'
WHEN time_dtm > SYSDATE -5 AND
time_dtm < SYSDATE -4 THEN 'Closed'
END) AS Age
FROM table_1
WHERE id IN (1,2,3)
-- The below will add one record for every desired Age group
UNION ALL
SELECT '0-1 day' FROM DUAL UNION ALL
SELECT '1-2 days' FROM DUAL UNION ALL
SELECT '2-3 days' FROM DUAL UNION ALL
SELECT '3-4 days' FROM DUAL UNION ALL
SELECT 'Closed' FROM DUAL
)
SELECT Age, COUNT(*) - 1 -- Subtract the extra record again
FROM data
GROUP BY Age
ORDER BY Age
Een geheel andere oplossing zou bestaan uit LEFT OUTER JOINs
:
-- Groups is a dynamic table that contains the date ranges and their "Age" label
WITH groups AS (
SELECT SYSDATE -1 lower, SYSDATE upper, '0-1 day' Age FROM DUAL UNION ALL
SELECT SYSDATE -2 , SYSDATE -1 , '1-2 days' FROM DUAL UNION ALL
SELECT SYSDATE -3 , SYSDATE -2 , '2-3 days' FROM DUAL UNION ALL
SELECT SYSDATE -4 , SYSDATE -3 , '3-4 days' FROM DUAL UNION ALL
SELECT SYSDATE -5 , SYSDATE -4 , 'Closed' FROM DUAL
)
SELECT g.Age, NVL(SUM(t.counter), 0)
FROM groups g
-- LEFT OUTER JOINing "table_1" to "groups" will ensure that every group
-- appears at least once in the result
LEFT OUTER JOIN (
SELECT 1 counter, t.* FROM table_1 t WHERE t.id IN (1,2,3)
) t
ON t.time_dtm >= g.lower
AND t.time_dtm < g.upper
GROUP BY g.Age
ORDER BY g.Age
In het tweede voorbeeld zou je ook zonder een CTE kunnen doen en een geneste SELECT gebruiken voor de groups
tafel. Het is gemakkelijk te zien hoe het tweede voorbeeld in de toekomst eenvoudiger te ontwikkelen is, mochten uw vereisten veranderen.