SQL查询以选择前14个月,如果缺少任何一个月,则添加金额“ 0”

时间:2019-12-06 06:42:49

标签: mysql sql date select

我已创建此查询来选择日期,前14个月的金额,在这种情况下,如果该月不存在任何记录,则该月将丢失,请建议我为该特定月份添加零和月的解决方案丢失。

SELECT dtSubscriptionRenewalDate, 
DATE_FORMAT(dtSubscriptionRenewalDate, "%b %Y") AS month,     
SUM(intPaymentAmount) as total 
FROM `tbl_pi_payment` 
WHERE strCurrencyCode = 'USD' 
and dtSubscriptionRenewalDate <= NOW() 
and dtSubscriptionRenewalDate >= Date_add(Now(),interval - 14 month) 
group by month  
ORDER BY `tbl_pi_payment`.`dtSubscriptionRenewalDate`  ASC;

enter image description here

您可以从结果中查看,缺少2018年11月。

4 个答案:

答案 0 :(得分:0)

您可以先生成月份和年份,然后再将其与查询结合起来-

SELECT dtSubscriptionRenewalDate, 
DATE_FORMAT(dtSubscriptionRenewalDate, "%b %Y") AS month,     
SUM(intPaymentAmount) as total 
FROM (SELECT 'January' AS months
      UNION 
      SELECT 'February'
      UNION 
      SELECT 'March'
      UNION 
      SELECT 'April'
      UNION 
      SELECT 'May'
      UNION 
      SELECT 'June'
      UNION 
      SELECT 'July'
      UNION 
      SELECT 'August'
      UNION 
      SELECT 'September'
      UNION 
      SELECT 'October'
      UNION 
      SELECT 'November'
      UNION 
      SELECT 'December') month
CROSS JOIN (SELECT 2018 AS years
            UNION
            SELECT 2019
            UNION 
            SELECT 2020) year
LEFT JOIN `tbl_pi_payment` tp ON YEAR(tp.dtSubscriptionRenewalDate) = year.years
                              AND MONTH(tp.dtSubscriptionRenewalDate) = month.months
WHERE strCurrencyCode = 'USD' 
and dtSubscriptionRenewalDate <= NOW() 
and dtSubscriptionRenewalDate >= Date_add(Now(),interval - 14 month) 
group by month  
ORDER BY `tbl_pi_payment`.`dtSubscriptionRenewalDate` ASC;

答案 1 :(得分:0)

尝试生成日历日期并设置JOIN

CREATE TABLE daterange (dte DATE); 

SET @counter := 15;
WHILE (@counter < 0) DO 
    INSERT daterange VALUES (SELECT DATE_SUB(CURDATE(), INTERVAL @counter:=@counter - 1 Month));
END WHILE;


SELECT dtSubscriptionRenewalDate, DATE_FORMAT(dte, "%b %Y") AS month, SUM(intPaymentAmount) as total 
FROM daterange D LEFT JOIN `tbl_pi_payment` T ON T.DATE_FORMAT(dtSubscriptionRenewalDate, "%b %Y") = D.DATE_FORMAT(dte , "%b %Y")
WHERE strCurrencyCode = 'USD' and dtSubscriptionRenewalDate <= NOW() and dtSubscriptionRenewalDate >= Date_add(Now(),interval - 14 month) 
GROUP BY DATE_FORMAT(dte, "%b %Y") 
ORDER BY `tbl_pi_payment`.`dtSubscriptionRenewalDate`  ASC;

答案 2 :(得分:0)

使用可能的月份的选择/联合创建一个临时表,然后从该表中左加入表,仅选择给定月份的记录。为了方便起见,请从几个月前的日期开始计算日期范围(但您可以只在联接中使用更复杂的表达式作为开始日期和结束日期)。

select
    min(dtSubscriptionRenewalDate) as min_renewal_date,
    date_format(date_sub(now(), interval months_ago month), "%b %Y") as month,
    coalesce(sum(intPaymentAmount),0) as total
from (
    select
        months_ago,
        date(date_format(date_sub(now(), interval months_ago month), "%Y-%m-01")) start_date,
        date(date_format(date_sub(now(), interval months_ago-1 month), "%Y-%m-01")) end_date
    from (select 0 months_ago union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 10 union select 11 union select 12 union select 13 union select 14 order by months_ago) months_ago
) date_range
left join tbl_pi_payment on
    dtSubscriptionRenewalDate >= start_date and
    dtSubscriptionRenewalDate < end_date and
    dtSubscriptionRenewalDate <= now() and
    strCurrencyCode = 'USD'
group by months_ago desc;

对于没有记录的月份,它将报告NULL作为续订日期,对于有记录的月份,将报告最小续订日期。不确定在那里到底想要什么。

答案 3 :(得分:0)

对于像这样的Oracle:

SELECT md.month AS month,     
SUM(intPaymentAmount) as total 
FROM `tbl_pi_payment` ,
(select add_month(trunc(sysdate,'MM')-level) month from dual connect by level <15) md
WHERE strCurrencyCode = 'USD' 
trunc(dtSubscriptionRenewalDate,'MM')(+)=md.month
group by md.month
ORDER BY md.month  ASC;