简体   繁体   English

MySQL 按日/月/年查询GROUP

[英]MySQL Query GROUP BY day / month / year

Is it possible to make a simple query to count how many records I have in a determined period of time like a year, month, or day, having a TIMESTAMP field, like:是否可以进行一个简单的查询来计算我在确定的时间段(如年、月或日)中有多少条记录,具有TIMESTAMP字段,如:

SELECT COUNT(id)
FROM stats
WHERE record_date.YEAR = 2009
GROUP BY record_date.YEAR

Or even:甚至:

SELECT COUNT(id)
FROM stats
GROUP BY record_date.YEAR, record_date.MONTH

To have a monthly statistic.每月统计一次。

Thanks!谢谢!

GROUP BY YEAR(record_date), MONTH(record_date)

查看 MySQL 中的日期和时间函数

GROUP BY DATE_FORMAT(record_date, '%Y%m')

Note (primarily, to potential downvoters).注意(主要是针对潜在的反对者)。 Presently, this may not be as efficient as other suggestions.目前,这可能不如其他建议有效。 Still, I leave it as an alternative, and a one, too, that can serve in seeing how faster other solutions are.尽管如此,我还是把它作为一个替代方案,它也可以用来了解其他解决方案的速度有多快。 (For you can't really tell fast from slow until you see the difference.) Also, as time goes on, changes could be made to MySQL's engine with regard to optimisation so as to make this solution, at some (perhaps, not so distant) point in future, to become quite comparable in efficiency with most others. (因为在看到差异之前,您无法真正区分快与慢。)此外,随着时间的推移,可以在优化方面对 MySQL 的引擎进行更改,以便在某些情况下(也许不是这样)遥远的)点在未来,变得与大多数其他人在效率上相当。

try this one试试这个

SELECT COUNT(id)
FROM stats
GROUP BY EXTRACT(YEAR_MONTH FROM record_date)

EXTRACT(unit FROM date) function is better as less grouping is used and the function return a number value. EXTRACT(unit FROM date)函数更好,因为使用较少的分组并且该函数返回一个数字值。

Comparison condition when grouping will be faster than DATE_FORMAT function (which return a string value).分组时的比较条件将比 DATE_FORMAT 函数(返回字符串值)更快。 Try using function|field that return non-string value for SQL comparison condition (WHERE, HAVING, ORDER BY, GROUP BY).尝试使用为 SQL 比较条件(WHERE、HAVING、ORDER BY、GROUP BY)返回非字符串值的函数|字段。

I tried using the 'WHERE' statement above, I thought its correct since nobody corrected it but I was wrong;我尝试使用上面的“WHERE”语句,我认为它是正确的,因为没有人纠正它,但我错了; after some searches I found out that this is the right formula for the WHERE statement so the code becomes like this:经过一番搜索,我发现这是 WHERE 语句的正确公式,因此代码变成了这样:

SELECT COUNT(id)  
FROM stats  
WHERE YEAR(record_date) = 2009  
GROUP BY MONTH(record_date)

If your search is over several years, and you still want to group monthly, I suggest:如果你搜索了几年,还想按月分组,我建议:

version #1:版本#1:

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY DATE_FORMAT(record_date, '%Y%m')

version #2 (more efficient) :版本#2 (更高效)

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY YEAR(record_date)*100 + MONTH(record_date)

I compared these versions on a big table with 1,357,918 rows ( ), and the 2nd version appears to have better results.我在一个有 1,357,918 行 ( ) 的大表上比较了这些版本,第二个版本似乎有更好的结果。

version1 (average of 10 executes) : 1.404 seconds version1 (平均执行 10 次) :1.404 秒
version2 (average of 10 executes) : 0.780 seconds version2 (平均执行 10 次) :0.780 秒

( SQL_NO_CACHE key added to prevent MySQL from CACHING to queries.) (添加了SQL_NO_CACHE键以防止 MySQL 对查询进行缓存。)

If you want to filter records for a particular year (eg 2000) then optimize the WHERE clause like this:如果要过滤特定年份(例如 2000 年)的记录,请像这样优化WHERE子句:

SELECT MONTH(date_column), COUNT(*)
FROM date_table
WHERE date_column >= '2000-01-01' AND date_column < '2001-01-01'
GROUP BY MONTH(date_column)
-- average 0.016 sec.

Instead of:代替:

WHERE YEAR(date_column) = 2000
-- average 0.132 sec.

The results were generated against a table containing 300k rows and index on date column.结果是针对包含 300k 行和日期列索引的表生成的。

As for the GROUP BY clause, I tested the three variants against the above mentioned table;至于GROUP BY子句,我针对上述表格测试了三个变体; here are the results:结果如下:

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY YEAR(date_column), MONTH(date_column)
-- codelogic
-- average 0.250 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY DATE_FORMAT(date_column, '%Y%m')
-- Andriy M
-- average 0.468 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY EXTRACT(YEAR_MONTH FROM date_column)
-- fu-chi
-- average 0.203 sec.

The last one is the winner.最后一位是赢家。

If you want to group by date in MySQL then use the code below:如果要在 MySQL 中按日期分组,请使用以下代码:

 SELECT COUNT(id)
 FROM stats
 GROUP BY DAYOFMONTH(record_date)

Hope this saves some time for the ones who are going to find this thread.希望这可以为将要找到此线程的人节省一些时间。

Complete and simple solution with similarly performing yet shorter and more flexible alternative currently active:完整而简单的解决方案,具有类似性能但更短、更灵活的替代方案,目前处于活动状态:

SELECT COUNT(*) FROM stats
-- GROUP BY YEAR(record_date), MONTH(record_date), DAYOFMONTH(record_date)
GROUP BY DATE_FORMAT(record_date, '%Y-%m-%d')

You can do this simply Mysql DATE_FORMAT() function in GROUP BY.您可以在 GROUP BY 中简单地执行 Mysql DATE_FORMAT()函数。 You may want to add an extra column for added clarity in some cases such as where records span several years then same month occurs in different years.Here so many option you can customize this.在某些情况下,您可能需要添加一个额外的列以增加清晰度,例如记录跨越几年的情况,然后在不同的年份出现相同的月份。这里有很多选项,您可以对此进行自定义。 Please read this befor starting.请在开始前阅读此内容。 Hope it should be very helpful for you.希望它对你很有帮助。 Here is sample query for your understanding这是您理解的示例查询

SELECT
    COUNT(id),
    DATE_FORMAT(record_date, '%Y-%m-%d') AS DAY,
    DATE_FORMAT(record_date, '%Y-%m') AS MONTH,
    DATE_FORMAT(record_date, '%Y') AS YEAR

FROM
    stats
WHERE
    YEAR = 2009
GROUP BY
    DATE_FORMAT(record_date, '%Y-%m-%d ');

If you want to get a monthly statistics with row counts per month of each year ordered by latest month, then try this:如果您想获得按最新月份排序的每年每月行数的月度统计数据,请尝试以下操作:

SELECT count(id),
      YEAR(record_date),
      MONTH(record_date) 
FROM `table` 
GROUP BY YEAR(record_date),
        MONTH(record_date) 
ORDER BY YEAR(record_date) DESC,
        MONTH(record_date) DESC

The following query worked for me in Oracle Database 12c Release 12.1.0.1.0以下查询在 Oracle Database 12c 版本 12.1.0.1.0 中对我有用

SELECT COUNT(*)
FROM stats
GROUP BY 
extract(MONTH FROM TIMESTAMP),
extract(MONTH FROM TIMESTAMP),
extract(YEAR  FROM TIMESTAMP);

I prefer to optimize the one year group selection like so:我更喜欢像这样优化一年组选择:

SELECT COUNT(*)
  FROM stats
 WHERE record_date >= :year 
   AND record_date <  :year + INTERVAL 1 YEAR;

This way you can just bind the year in once, eg '2009' , with a named parameter and don't need to worry about adding '-01-01' or passing in '2010' separately.通过这种方式,您只需将年份绑定一次,例如'2009' ,使用命名参数,而无需担心添加'-01-01'或单独传入'2010'

Also, as presumably we are just counting rows and id is never NULL , I prefer COUNT(*) to COUNT(id) .另外,大概我们只是在计算行数,而id永远不会是NULL ,我更喜欢COUNT(*)COUNT(id)

.... group by to_char(date, 'YYYY') --> 1989 .... group by to_char(date, 'YYYY') --> 1989

.... group by to_char(date,'MM') -->05 .... group by to_char(date,'MM') -->05

.... group by to_char(date,'DD') --->23 .... group by to_char(date,'DD') --->23

.... group by to_char(date,'MON') --->MAY .... group by to_char(date,'MON') ---> MAY

.... group by to_char(date,'YY') --->89 .... group by to_char(date,'YY') --->89

Here's one more approach.这是另一种方法。 This uses [MySQL's LAST_DAY() function][1] to map each timestamp to its month.这使用 [MySQL 的 LAST_DAY() 函数][1] 将每个时间戳映射到它的月份。 It also is capable of filtering by year with an efficient range-scan if there's an index on record_date .如果record_date上有索引, record_date能够通过有效的范围扫描按年份过滤。

  SELECT LAST_DAY(record_date) month_ending, COUNT(*) record_count
    FROM stats
   WHERE record_date >= '2000-01-01'
     AND record_date <  '2000-01-01' + INTERVAL 1 YEAR
   GROUP BY LAST_DAY(record_date) 

If you want your results by day, use DATE(record_date) instead.如果您希望按天显示结果,请改用DATE(record_date)

If you want your results by calendar quarter, use YEAR(record_date), QUARTER(record_date) .如果您希望按日历季度显示结果,请使用YEAR(record_date), QUARTER(record_date)

Here's a writeup.这里有一篇记叙文。 https://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/ [1]: https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_last-day https://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/ [1]: https : //dev.mysql.com/doc/refman/8.0/en/date-and-time-functions。 html#function_last-day

I wanted to get similar data per day, after experimenting a bit, this is the fastest I could find for my scenario我想每天获得类似的数据,经过一些试验,这是我能找到的最快的场景

SELECT COUNT(id)
FROM stats
GROUP BY record_date DIV 1000000;

If you want to have it per month, add additional zeroes (00) I would not recommend this from "make the code readable" perspective, it might also break in different versions.如果您想每月使用它,请添加额外的零 (00) 从“使代码可读”的角度来看,我不建议这样做,它也可能会在不同版本中中断。 But in our case this took less then half the time compared to some other more clearer queries that I tested.但在我们的例子中,与我测试的其他一些更清晰的查询相比,这花费的时间不到一半。

This is a MySQL answer (as MySQL is tagged in the question) and well documented in the manual https://dev.mysql.com/doc/refman/8.0/en/date-and-time-type-conversion.html这是一个 MySQL 答案(因为 MySQL 在问题中被标记)并且在手册https://dev.mysql.com/doc/refman/8.0/en/date-and-time-type-conversion.html 中有详细记录

try it试试看

GROUP BY YEAR(record_date), MONTH(record_date) GROUP BY YEAR(record_date), MONTH(record_date)

Or you can use group by clause like this,或者你可以像这样使用 group by 子句,

//to get data by month and year do this ->
SELECT FORMAT(TIMESTAMP_COLUMN, 'MMMM yy') AS Month, COUNT(ID) FROM TABLE_NAME GROUP BY FORMAT(TIMESTAMP_COLUMN, 'MMMM yy')

if you want to fetch records by date then in group by change format to 'dd-mm-yy' or 'dd-MMMM-yyy'如果你想按日期获取记录,然后在组中将格式更改为 'dd-mm-yy' 或 'dd-MMMM-yyy'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM