在MySQL中按月和年分组


95

给定一个在每行上都有时间戳的表,您将如何格式化查询以适合此特定的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";

该查询正在分解,因为它(可预测地)将不同年份组合在一起。

Answers:


185
GROUP BY YEAR(t.summaryDateTime), MONTH(t.summaryDateTime) DESC;

是你想要的。


60
+1:使用DATE_FORMAT的另一种选择:DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG小马,2010年

3
进一步地,如果您的数据库中有UNIX时间戳,则需要FROM_UNIXTIMEDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo 2012年

感谢@OMGPonies,使用您的语法,我可以执行条件GROUP BY。
亨利

性能...我在具有300,000个条目的InnoDB表上对GROUP BY YEAR(date), MONTH(date) DESC;(〜450 ms)和GROUP BY DATE_FORMAT(date,'%Y-%m')(〜850 ms)的测试表明,前者(此问题的标记答案)花费了后者的一半时间。
ow3n

77
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')

欢迎来到StackOverflow!这是一个古老且已经回答的问题。如果您也可以提出更多紧迫的问题,我们将很高兴。您可以在此处找到有关提供良好答案的提示。
Mifeet 2014年

请参阅我对以上答案的评论...在大型桌子上,此方法花费的时间是原来的两倍。
ow3n

9

我更喜欢

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

8
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

在YEAR和Month都应使用DESC,以获取正确的订单。


7

我知道这是一个古老的问题,但是如果您不需要数据库级别的月份名称,则可以使用以下方法:

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

请参阅EXTRACT函数文档

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

注意:我不知道您可以在MySQL的GROUP BY子句中添加DESC,也许您缺少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;

1
请注意,输出EXTRACT(YEAR_MONTH FROM summaryDateTime)201901
Edgar Ortega,

@EdgarOrtega是的,但这足以使用应用程序逻辑在原始问题中生成所需的JSON对象。假设某种形式的查询结果循环已经在发生,我的方法旨在尽可能简单,快速地从数据库中获取最少的信息
Arth,

1
您是对的,这应该足够了。我的评论只是表明该函数的输出是什么样,也许有人不喜欢该格式。
Edgar Ortega,

@EdgarOrtega不用担心,谢谢,值得的贡献!
Arth

2

你必须做这样的事情

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

2

您也可以这样做

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

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



1

这是我的方法:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);


0
SELECT YEAR(t.summaryDateTime) as yr, GROUP_CONCAT(MONTHNAME(t.summaryDateTime)) AS month 
FROM trading_summary t GROUP BY yr

仍然需要在外部脚本中对其进行处理,以准确获取所需的结构。

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


-2

GROUP BY year, month DESC";

代替

GROUP BY MONTH(t.summaryDateTime) DESC";

尽管看来出于某些原因,GROUP BY MONTH(t.summaryDateTime)DESC不能正确订购月份……
Derek Adair 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.