Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Nullwert zurückgeben, wenn keine Zeilendaten vorhanden sind

Schreiben Sie zunächst Ihre Abfrage neu. Verwenden Sie Ansichten oder allgemeine Tabellenausdrücke, damit Sie sich nicht dreimal für Ihr SELECT wiederholen müssen , GROUP BY , ORDER BY Klauseln. Ihre Abfrage wird zu:

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

Um dann sicherzustellen, dass jede Ihrer gewünschten Gruppen im Ergebnis verfügbar ist, haben Sie viele Optionen.

Sie könnten UNION ALL verwenden :

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

Eine ganz andere Lösung würde LEFT OUTER JOINs beinhalten :

-- 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

Im zweiten Beispiel könnte man auch auf einen CTE verzichten und ein verschachteltes SELECT für die groups verwenden Tisch. Es ist leicht zu erkennen, wie sich das zweite Beispiel in Zukunft einfacher weiterentwickeln lässt, falls sich Ihre Anforderungen ändern sollten.