【问题标题】:How to add month name with 0 total if data not exist in mysql?如果mysql中不存在数据,如何添加总为0的月份名称?
【发布时间】:2019-10-13 10:37:07
【问题描述】:

我需要从created_date 获取用户的数据,直到当前数据按月份名称和年份以及每个月的总价。

尝试 1:

SELECT MONTHNAME(start_time) month, YEAR(start_time) year, SUM(price) total
FROM table t1
WHERE t1.id= 33
GROUP BY YEAR(start_time), MONTH(start_time);

输出:

month           year    total
July            2019    360
September       2019    2160
October         2019    360

预期输出:

All month name and total will be 0 if data not exist. 

month           year    total
Jan             2018    0
Feb             2018    0
...
Dec             2018    0
Jan             2019    0
Feb             2019    0
Mar             2019    0
Apr             2019    0
May             2019    0
Jun             2019    0
July            2019    360
Aug             2019    0
Sep             2019    2160
Oct             2019    360
Nov             2019    0
Dec             2019    0

经过一些 RND,我找到了一种方法,我也尝试过,但现在可以了。

尝试 2:

 SELECT IFNULL(SUM(ri.price),0) AS total, m.month
 FROM (
       SELECT 'Jan' AS MONTH
       UNION SELECT 'Feb' AS MONTH
       UNION SELECT 'Mar' AS MONTH
       UNION SELECT 'Apr' AS MONTH
       UNION SELECT 'May' AS MONTH
       UNION SELECT 'Jun' AS MONTH
       UNION SELECT 'Jul' AS MONTH
       UNION SELECT 'Aug' AS MONTH
       UNION SELECT 'Sep' AS MONTH
       UNION SELECT 'Oct' AS MONTH
       UNION SELECT 'Nov' AS MONTH
       UNION SELECT 'Dec' AS MONTH
      ) AS m
LEFT JOIN table_u pu 
ON MONTH(STR_TO_DATE(CONCAT(pu.created_date, '2019'),'%M %Y')) = MONTH(pu.created_date)
AND YEAR(pu.created_date) = '2019'
LEFT JOIN table ri 
ON ri.id = pu.id
GROUP BY m.month
ORDER by 1+1;

这是我的refrence 链接。

谁能帮我解决这个问题?

提前致谢。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    继续使用LEFT JOIN(但只使用一次)和最多 12 个整数生成器(而不是月份名称,也可以在 ORDER BY 子句中轻松使用),因为您可以通过 monthname() 函数获取月份名称.从您的第二个查询中,我考虑了当前年份。所以,使用:

    SET @year=YEAR(NOW());
    
    SELECT 
          MONTHNAME(STR_TO_DATE(concat(YEAR(NOW()),',',m.month,',1'),"%Y,%m,%d")) as month,
          @year as year , SUM( COALESCE( pu.price, 0) ) as total
      FROM (
            SELECT rn as month 
              FROM
              (
               SELECT @rn := if(@i = @rn, @rn + 1, 1) as rn,
                      @i := @i+1
                 FROM information_schema.character_sets
                 JOIN (SELECT @i := 0, @rn := 0) as q_iter
                LIMIT 12
              ) q
            ) AS m
       LEFT JOIN table_u pu ON MONTH(pu.start_time) = m.month
        AND YEAR(pu.start_time) = @year
        AND ID = 33
      GROUP BY m.month
      ORDER by m.month;
    

    Demo 1

    编辑从 2018 年初到今年年底):

    SELECT MONTHNAME(
             STR_TO_DATE(
               CONCAT(m.year,',',if(mod(m.month,12)=0,12,mod(m.month,12)),',1'),"%Y,%m,%d")
               ) 
           as month, 
           year, 
           SUM( CASE WHEN YEAR(pu.start_time) = m.year AND MONTH(pu.start_time) = m.month
                     THEN 
                          COALESCE( pu.price, 0) 
                     ELSE
                          0
                END ) as total 
      FROM
      (
           SELECT @i := if( @i = 12 , 1 , @i+1) as month,
                  @j := @j + 1,    
                  @k:= if( @i = 1 and @j > 12, @k - 1, @k ) as year
                 FROM information_schema.character_sets
             JOIN (SELECT @i := 0, @j := 0, @k:=YEAR(now())) as q_iter
       ) m
       LEFT JOIN table_u pu ON MONTH(pu.start_time) = m.month    
        AND ID = 33
      GROUP BY month, year
     HAVING year >= ( SELECT MIN( YEAR(start_time) ) FROM table_u  )
      ORDER BY year, m.month;
    

    Demo 2

    【讨论】:

    • 好的,我一会儿试试,告诉你。
    • 我已经检查过了,这在今年可以正常工作。我只需要再上一层。例如,我有一个日期2018-10-10 然后我需要从 2010 年到当前月份的数据。
    • 顺便说一句,这个查询看起来很棒。我从来没有想过我可以运行这种类型的查询。也许可能需要一些时间才能理解这是如何工作的。 :)
    • 好的,我修复了@SachinShah。
    • 感谢@Barbaros Özhan。我会检查并通知您。
    【解决方案2】:

    如果您的表中有所有个月的数据,但只是没有id,那么您可以切换到条件聚合:

    SELECT MONTHNAME(start_time) as month, YEAR(start_time) as year, 
           SUM(CASE WHEN t1.id = 33 THEN price ELSE 0 END) as total
    FROM table t1
    GROUP BY YEAR(start_time),MONTHNAME(start_time)
    ORDER BY MIN(start_time);
    

    【讨论】:

    • 感谢您的回答。就我而言,我不可能在一年中为特定用户设置月份名称。例如,他 3 个月没有工作,那么我需要给他看 0 对应的月份。
    • @SachinShah。 . .您错过了重点(并且显然没有运行查询)。如果您的数据中有 any id 的月份,则月份将在使用此查询的结果集中。该数据仅适用于33
    【解决方案3】:

    使用用户变量创建不存在的年月对:

    SELECT monthname(str_to_date(concat_ws(',',ym.month,'01,01'),'%m,%d,%y')) month
         , ym.year year 
         , sum(price)
      FROM table1 t1
        RIGHT JOIN( SELECT @year  := if(@month=12, @year+1, @year   ) year
                        , @month := if(@month=12, 1      , @month+1) month
                     FROM table1
                        , ( SELECT @startYear := min(start_time)
                                 , @endYear   := year(now())
                                 , @month := 12
                                 , @year  := min(start_time)-1
                              FROM table1
                          ) t
                     WHERE (@year,@month) < (@endYear,12)
                 ) ym
          ON    ym.year  = year(t1.start_time)
            AND ym.month = month(t1.start_time)
      GROUP BY year(t1.start_time)
             , month(t1.start_time)
    

    ym 派生表用于提供从 table1 中的最小年份开始到当前年份的年月对。 最里面的 SELECT 用于变量初始化。

    【讨论】:

    • 感谢您的回复。它对我不起作用。我得到了这个输出。 month year sum(price) January NULL 360 January NULL 2160 January NULL 360 你能检查我的预期输出吗? :)
    【解决方案4】:

    你可以试试这个:

    SELECT to_char(start_time,'month')MONTH,to_char(start_time,'yyyy')YEAR,SUM(price)total 
    FROM   TABLE_NAME
    GROUP BY to_char(start_time,'month'),to_char(start_time,'yyyy')
    

    【讨论】:

    • 感谢您的回复。我会检查并通知您。
    • to_char 是默认函数吗?
    • 是的! to_char 是默认函数。使用日期将被转换为字符串。有关更多信息,请参阅下面的链接。 link
    • 好的,我会再试一次,然后告诉你。
    • FUNCTION TO_CHAR does not exist
    【解决方案5】:

    最后,我得到了我想要的正确输出。

    select
    DATE_FORMAT(m1, '%M - %Y')
    
    from
    (
      select
      ('2013-07-23')
      +INTERVAL m MONTH as m1
      from
      (
         select @rownum:=@rownum+1 as m from
         (select 1 union select 2 union select 3 union select 4) t1,
         (select 1 union select 2 union select 3 union select 4) t2,
         (select 1 union select 2 union select 3 union select 4) t3,
         (select 1 union select 2 union select 3 union select 4) t4,
         (select @rownum:=-1) t0
      ) d1
    ) d2
      where m1<=NOW()
      order by m1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 2013-03-08
      • 2022-08-02
      • 1970-01-01
      相关资源
      最近更新 更多