sql >> Databasteknik >  >> RDS >> Oracle

Returnera nollvärde när ingen raddata finns

Först och främst, skriv om din fråga. Använd vyer eller vanligt tabelluttryck för att undvika att upprepa dig själv tre gånger för din SELECT , GROUP BY , ORDER BY klausuler. Din fråga blir:

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

Sedan, för att vara säker på att någon av dina önskade grupper kommer att vara tillgängliga i resultatet, har du massor av alternativ.

Du kan använda UNION ALL :

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

En helt annan lösning skulle involvera 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

I det andra exemplet kan du också klara dig utan en CTE och använda en kapslad SELECT för groups tabell. Det är lätt att se hur det andra exemplet är enklare att utvecklas i framtiden om dina krav skulle ändras.




  1. Hitta median mellan TVÅ datum SQL Server 2008

  2. MySQL C API-kompileringsfel, crtdbg.h hittades inte

  3. Hur matar man ut text från databasen med radbrytningar i en django-mall?

  4. Hur kan jag få databasnamnet jag är ansluten till via Hibernate?