我看到过与此类似的帖子数量,但没有一个非常适合我正在使用的场景。尝试查询数据库并汇总过去每个月的结果12.如果特定月份没有结果,我希望该特定月份连续0。
运行此查询会生成2016年11月至2017年3月的数据,之前/之后没有结果:
SELECT SUM(PRICE) SumPrice, COUNT(*) TotalNum, EXTRACT(MONTH FROM SALE_DATE) Mo, EXTRACT(YEAR FROM SALE_DATE) Yr
FROM SALES_HIST
WHERE SALE_DATE BETWEEN TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12))
AND LAST_DAY(SYSDATE)
AND ITEMNO = 'ABCD'
GROUP BY EXTRACT(MONTH FROM SALE_DATE), EXTRACT(YEAR FROM SALE_DATE)
ORDER BY Yr, Mo;
经过一番搜索后,我想出了这个查询,以便生成过去12个月的列表:
SELECT
EXTRACT(MONTH FROM
ADD_MONTHS(TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12)), LEVEL - 1)) calMo,
EXTRACT(YEAR FROM
ADD_MONTHS(TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12)), LEVEL - 1)) calYr
FROM DUAL
CONNECT BY LEVEL <= 12;
我相信我应该能够在我的查询中使用它作为临时表来填补数据空白。这就是我一直在修补的:
WITH cal AS (
SELECT
EXTRACT(MONTH FROM ADD_MONTHS(TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12)), LEVEL - 1)) calMo,
EXTRACT(YEAR FROM ADD_MONTHS(TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12)), LEVEL - 1)) calYr
FROM DUAL
CONNECT BY LEVEL <= 12
)
select cal.calMo, cal.calYr, NVL(count(*), 0)
from cal
left join SALES_HIST sh on cal.calMo = EXTRACT(MONTH FROM sh.SALE_DATE)
WHERE SALE_DATE BETWEEN TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12)) AND LAST_DAY(SYSDATE)
AND ITEMNO = 'ABCD'
group by cal.calMo, cal.calYr
order by cal.calYr, cal.calMo;
但这似乎返回与初始查询相同的结果。我假设我错过了加入的东西,但不确定。任何帮助将不胜感激。谢谢!
答案 0 :(得分:0)
当您使用WHERE子句时,它会过滤掉WHERE子句中条件未满足的LEFT JOIN的所有结果行,因此将删除所有NULL值。如果在sales_hist表的条件中使用AND,它将在创建与cal表中的月/年不匹配的NULL值之前首先过滤这些记录。另外,在计数上使用sh.itemno而不是*,因为它将计算cal表中每个月有1的条目。
SELECT cal.calmo,
cal.calyr,
NVL(COUNT(sh.itemno), 0) /*changed from * to sh.itemno*/
FROM cal
LEFT JOIN sales_hist sh
ON cal.calMo = EXTRACT(MONTH FROM sh.sale_date)
AND sale_date BETWEEN TRUNC(ADD_MONTHS((LAST_DAY(SYSDATE)+1),-12))
AND LAST_DAY(SYSDATE) /*changed from WHERE to AND*/
AND itemno = 'ABCD'
GROUP BY cal.calmo,
cal.calyr
ORDER BY cal.calyr,
cal.calmo;
示例数据
CREATE TABLE sales_hist AS
SELECT TO_DATE('09172017','MMDDYYYY') sale_date,
'ABCD' itemno
FROM dual
UNION ALL
SELECT TO_DATE('10172016','MMDDYYYY') sale_date,
'ABCD' itemno
FROM dual
UNION ALL
SELECT TO_DATE('10182016','MMDDYYYY') sale_date,
'ABCD' itemno
FROM dual
UNION ALL
SELECT TO_DATE('09172016','MMDDYYYY') sale_date,
'ABCD' itemno
FROM dual
;
示例结果。请注意,09172016不包括在计数中。
CALMO CALYR NVL(COUNT(SH.ITEMNO),0)
10 2016 2
11 2016 0
12 2016 0
1 2017 0
2 2017 0
3 2017 0
4 2017 0
5 2017 0
6 2017 0
7 2017 0
8 2017 0
9 2017 1