我之前已经解决了我的问题,但我似乎无法将任何解决方案应用于我的查询以使其正常工作。非常感谢一些指导。
我当前的查询返回此数据集:
| Age | Count | 0-1 day 300 2-3 days 6000 3-4 days 100
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,
COUNT( * ) AS "Count"
FROM table_1
WHERE id IN (1,2,3)
GROUP BY (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)
ORDER BY (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)
但是,我希望它将零/空行显示为零:
| Age | Count | 0-1 day 300 1-2 days 0 2-3 days 6000 3-4 days 100 Closed 0
我已经阅读了过去几天的所有种类:NVL,COALESCE,FULL / LEFT / RIGHT OUTER JOIN,LEFT / RIGHT JOINS,UNION ALL等没有一个有CASE声明并试图解决它我自己但是!你必须知道何时停下来并询问方向。
答案 0 :(得分:3)
首先,重新编写查询。使用视图或公用表表达式可避免对SELECT
,GROUP BY
,ORDER BY
子句重复三次。您的查询变为:
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
然后,为了确保您在结果中可以使用任何所需的组,您有很多选择。
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
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
在第二个示例中,您也可以不使用CTE并使用groups
表的嵌套SELECT。如果您的需求发生变化,很容易看出第二个示例在未来如何更容易发展。