【问题标题】:SQL query to select previous 14 months where add amount '0' if any month is missingSQL 查询选择前 14 个月,如果缺少任何月份,则添加金额“0”
【发布时间】:2019-12-06 06:42:49
【问题描述】:

我创建了这个查询来选择日期,前 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;

从结果中可以看出,那 NOv 2018 是缺失的。

【问题讨论】:

  • 您有 2018 年 11 月的数据吗?
  • 否,表中没有 2018 年 11 月的记录
  • 这种情况下,您期望 2018 年 11 月的行应该如何出现在输出中?如果您需要开始日期和结束日期之间的所有可用月份,则必须使用日历表,或者您可以在另一个查询中生成月份列表,然后加入您的主查询。
  • 请告诉我这是怎么做的?
  • 创建月份统计表,然后加入您的查询。

标签: mysql sql date select


【解决方案1】:

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

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 为没有记录的月份的续订日期,以及有记录的月份的最短续订日期。不知道你到底想要什么。

【讨论】:

    【解决方案2】:

    您可以先生成月份和年份,然后可以将其与您的查询一起加入 -

    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;
    

    【讨论】:

    • 不会正确排序没有数据的月份
    【解决方案3】:

    尝试生成日历日期并将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;
    

    【讨论】:

      【解决方案4】:

      对于这样的甲骨文:

      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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-08
        • 2013-03-30
        • 1970-01-01
        相关资源
        最近更新 更多