【问题标题】:Group by month and year in MySQL在 MySQL 中按月和年分组
【发布时间】:2011-03-22 23:12:52
【问题描述】:

给定一个表,每行都有一个时间戳,你将如何格式化查询以适应这种特定的 json 对象格式。

我正在尝试将 json 对象组织成年/月。

json 来作为查询的基础:

{
  "2009":["August","July","September"],
  "2010":["January", "February", "October"]
}

这是我目前的查询 -

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY MONTH(t.summaryDateTime) DESC";

查询失败了,因为它(可以预见地)将不同年份混为一谈。

【问题讨论】:

    标签: sql mysql group-by date


    【解决方案1】:

    由于要按月提取此数据以进行交易摘要,因此我不得不做同样的事情,并且只想添加我使用的代码。我拥有的数据作为字符串保存在数据库中,因此您的查询可能更简单。无论哪种方式,作为交易者,这本质上都是大多数人想要的:

    select
        DATE(DATE_FORMAT(STR_TO_DATE(closeDate, '%Y-%m-%d'), '%Y-%m-01')) AS month_beginning,
        COUNT(*) AS trades,
        TRUNCATE(sum(profitLoss)/count(*),2) as 'avgProfit',
        TRUNCATE(sum(percentGain)/count(*),2) as 'avgPercent',
        sum(profitLoss) as 'gi',
        sum(profitLoss > 0)/count(*) AS winPercent,
        sum(profitLoss < 0)/count(*) as 'lossPercent',
        max(profitLoss) as bigWinner,
        min(profitLoss) as bigLoser
    from tradeHistory
    group by month_beginning
    order by month_beginning DESC
    

    但是,它会跳过数据中缺少的月份。所以如果一月没有数据,就不会有一行。

    【讨论】:

      【解决方案2】:

      我想添加按年(日期时间)、月(日期时间)分组和按提取(日期时间的年月)分组之间的差异。 这是我在这两种情况下尝试的查询。

      从表中选择 year(datetimecol) 作为 Year,monthname(datetimecol) 作为 Month
      按年份(datetimecol) 和月份(datetimecol) 分组 按年份(datetimecol) desc;

      结果:

      年、月

      2020 年 5 月

      从表中选择年份(datetimecol)作为年份,月份名称(datetimecol)作为月份 GROUP BY EXTRACT(YEAR_MONTH FROM datetimecol) 按年排序(datetimecol) desc,month(datetimecol) asc;

      结果:

      年、月

      2021 年 1 月 2021 年 2 月 2021 年 3 月 2021 年 4 月 2021 年 5 月 2020 年 5 月 2020 年 6 月 2020 年 7 月 2020 年 8 月 2020 年 9 月 2020 年 10 月 2020 年 11 月 2020年12月

      (这是我需要的结果)

      我的观察 1.当我使用 group by year(datetimecol),month(datetimecol) 时,没有给出想要的结果..可能是因为 datetime feild... 2.当我厌倦了使用 GROUP BY EXTRACT(YEAR_MONTH FROM datetimecol) order by year(datetimecol) 进行第二次查询时......它工作得非常好。

      总之,要逐年获取月份,请使用以下查询。

      从表中选择年份(datetimecol)作为年份,月份名称(datetimecol)作为月份 GROUP BY EXTRACT(YEAR_MONTH FROM datetimecol) 按年排序(datetimecol) desc,month(datetimecol) asc;

      【讨论】:

      • 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review
      • 我尝试了这个上下文并给出了我的观察结果。我没有经过测试就给出了。
      【解决方案3】:

      我更喜欢

      SELECT
          MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
      FROM
          trading_summary t 
      GROUP BY EXTRACT(YEAR_MONTH FROM t.summaryDateTime);
      

      【讨论】:

        【解决方案4】:
        GROUP BY YEAR(t.summaryDateTime), MONTH(t.summaryDateTime);
        

        是你想要的。

        【讨论】:

        • +1:使用DATE_FORMAT的另一种选择:DATE_FORMAT(t.summaryDateTime, '%Y-%m')
        • 此外,如果您的数据库中有 UNIX 时间戳DATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' ),则需要FROM_UNIXTIME
        • 感谢@OMGPonies,使用您的语法,我可以执行条件 GROUP BY。
        • Performance... 我在 InnoDB 表上对 GROUP BY YEAR(date), MONTH(date) DESC; (~450 ms) 和 GROUP BY DATE_FORMAT(date,'%Y-%m') (~850 ms) 的测试显示了前者(该问题的标记答案) 花费了后者的大约一半时间。
        【解决方案5】:

        这就是我的做法:

        GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);
        

        【讨论】:

          【解决方案6】:

          我知道这是一个老问题,但如果您不需要数据库级别的月份名称,以下应该可以工作:

            SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
              FROM trading_summary  
          GROUP BY summary_year_month;
          

          See EXTRACT function docs

          您可能会发现它的性能更好。如果您在应用层构建 JSON 对象,您可以在运行结果时进行格式化/排序。

          注意我不知道您可以将 DESC 添加到 MySQL 中的 GROUP BY 子句中,也许您缺少 ORDER BY 子句:

            SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
              FROM trading_summary  
          GROUP BY summary_year_month
          ORDER BY summary_year_month DESC;
          

          【讨论】:

          • 请注意EXTRACT(YEAR_MONTH FROM summaryDateTime)的输出是201901
          • @EdgarOrtega 是的,但这应该足以使用应用程序逻辑在原始问题中生成所需的 JSON 对象。假设已经发生了某种形式的查询结果循环,我的方法旨在尽可能简单快速地从数据库中获取所需的最少信息
          • 你说得对,应该够了。我的评论只是为了说明该函数的输出是什么样的,也许有人不喜欢这种格式。
          • @EdgarOrtega 不用担心,谢谢,值得的贡献!
          【解决方案7】:

          你也可以这样做

          SELECT  SUM(amnt) `value`,DATE_FORMAT(dtrg,'%m-%y') AS label FROM rentpay GROUP BY YEAR(dtrg) DESC, MONTH(dtrg) DESC LIMIT 12
          

          按年和月订购。假设您想从今年和本月一直到 12 个月订购

          【讨论】:

            【解决方案8】:

            像这样使用 EXTRACT 函数

            mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
                   -> 2009
            

            【讨论】:

              【解决方案9】:

              你必须这样做

              SELECT onDay, id, 
              sum(pxLow)/count(*),sum(pxLow),count(`*`),
              CONCAT(YEAR(onDay),"-",MONTH(onDay)) as sdate 
              FROM ... where stockParent_id =16120 group by sdate order by onDay
              

              【讨论】:

                【解决方案10】:
                GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')
                

                【讨论】:

                • 欢迎来到 StackOverflow!这是一个古老且已经回答的问题。如果您也能为更紧迫的问题做出贡献,我们将很高兴。您可以找到有关提供良好答案的提示here
                • 查看我对上述答案的评论...在大型表上,此方法需要两倍的时间。
                【解决方案11】:
                SELECT MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
                FROM trading_summary t
                GROUP BY YEAR(t.summaryDateTime) DESC, MONTH(t.summaryDateTime) DESC
                

                应同时使用 DESC 表示 YEAR 和 Month 以获得正确的顺序。

                【讨论】:

                  【解决方案12】:

                  使用

                  GROUP BY year, month DESC";
                  

                  代替

                  GROUP BY MONTH(t.summaryDateTime) DESC";
                  

                  【讨论】:

                  • 虽然看起来 GROUP BY MONTH(t.summaryDateTime) DESC 由于某种原因没有正确排序月份...
                  【解决方案13】:
                  SELECT YEAR(t.summaryDateTime) as yr, GROUP_CONCAT(MONTHNAME(t.summaryDateTime)) AS month 
                  FROM trading_summary t GROUP BY yr
                  

                  您仍然需要在外部脚本中对其进行处理才能准确获得您正在寻找的结构。

                  例如使用 PHP 的 explode 从月份名称列表中创建一个数组,然后使用 json_encode()

                  【讨论】:

                    【解决方案14】:

                    您只按月份分组,您必须将 YEAR() 添加到分组中

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2012-12-10
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-07-21
                      • 2021-10-16
                      相关资源
                      最近更新 更多