Oracle:根据选定年份查询12条月度汇总数据的SQL实现
解决方案
假设你的表名为MONTHLY_STATS,可以使用以下SQL实现需求,通过绑定变量:p_selected_year传入你要查询的年份:
SELECT ID, Month, Year, "Sum of objects" FROM MONTHLY_STATS WHERE -- 场景1:查询过去年份,返回该年全部12个月数据 (:p_selected_year <> EXTRACT(YEAR FROM SYSDATE) AND Year = :p_selected_year AND Month BETWEEN 1 AND 12) OR -- 场景2:查询当前年份,返回今年已过月份 + 去年剩余月份凑足12条 (:p_selected_year = EXTRACT(YEAR FROM SYSDATE) AND ( -- 当前年的1到当前月份 (Year = :p_selected_year AND Month <= EXTRACT(MONTH FROM SYSDATE)) OR -- 去年的(当前月份+1)到12月份 (Year = :p_selected_year - 1 AND Month > EXTRACT(MONTH FROM SYSDATE)) )) -- 按时间顺序排序,确保结果从早到晚排列 ORDER BY Year, Month;
为什么你的之前尝试失败?
Oracle的CASE表达式无法直接返回布尔条件(比如BETWEEN...AND),它只能返回具体值,所以你之前在WHERE里用CASE的写法会导致语法或逻辑错误。改用逻辑分支(OR)拆分两种场景,就能清晰实现需求。
补充说明
- 如果你的
Month列是字符串类型(比如'01'、'02'),需要先转换成数字类型再比较,比如TO_NUMBER(Month)。 - 如果某些月份没有统计数据(表中无对应记录),需要返回
Sum of objects为0的行,可以用CONNECT BY生成12个目标月份,再与表做左连接,示例如下:
WITH target_months AS ( SELECT CASE WHEN :p_selected_year = EXTRACT(YEAR FROM SYSDATE) THEN CASE WHEN rn <= EXTRACT(MONTH FROM SYSDATE) THEN :p_selected_year ELSE :p_selected_year -1 END ELSE :p_selected_year END AS target_year, CASE WHEN :p_selected_year = EXTRACT(YEAR FROM SYSDATE) THEN CASE WHEN rn <= EXTRACT(MONTH FROM SYSDATE) THEN rn ELSE rn - EXTRACT(MONTH FROM SYSDATE) END ELSE rn END AS target_month FROM (SELECT ROWNUM rn FROM DUAL CONNECT BY ROWNUM <=12) ) SELECT tm.target_year AS Year, tm.target_month AS Month, NVL(ms."Sum of objects", 0) AS "Sum of objects" FROM target_months tm LEFT JOIN MONTHLY_STATS ms ON ms.Year = tm.target_year AND ms.Month = tm.target_month ORDER BY tm.target_year, tm.target_month;
内容的提问来源于stack exchange,提问作者Vladimir Irkhin
相关产品推荐
相关产品推荐

