如何在MySQL中按周分组?

Oracle的表服务器提供了一个内置函数TRUNC(timestamp,'DY') 。 这个函数将前一个星期天的任何时间戳转换为午夜。 什么是在MySQL中做到这一点的最好方法?

Oracle还提供了TRUNC(timestamp,'MM') ,将时间戳转换为发生月份的第一天的午夜。 在MySQL中,这个很简单:

 TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01')) 

但是这个DATE_FORMAT技巧在几个星期内不会运行。 我知道WEEK(timestamp)function,但我真的不希望在一年内的周数; 这东西是为了多年的工作。

您可以同时使用YEAR(timestamp)WEEK(timestamp) ,并在SELECTGROUP BY子句中使用这两个expression式。

不是太优雅,但function…

当然,您也可以将这两个date部分组合成一个expression式,即类似的东西

 SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc... FROM ... WHERE .. GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp)) 

编辑 :正如马丁xx指出,你也可以使用YEARWEEK(mysqldatefield)函数,虽然它的输出不像上面的公式长得那么友善。

编辑2 [3年半后!]:
YEARWEEK(mysqldatefield)与可选的第二个参数( mode )设置为0或2可能是最好的方式来聚集完整的星期(即包括几个星期跨越1月1日),如果这是所需的。 在这个答案中最初提出的YEAR() / WEEK()方法的效果是将这种“跨界”周的汇总数据分成两部分:一部分是前一年,一部是新年。
每年都要进行一次干净的裁员,而且要花费最多两个部分的时间,一方面要在会计等方面进行, YEAR() / WEEK()YEAR() / WEEK()方法则更好。

您可以使用YEARWEEK()函数获取连结的年份和星期编号(200945)。 如果我能正确理解你的目标,那么你应该可以把你的多年数据分组。

如果您需要本周开始的实际时间戳,那就不太好了:

 DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY ) 

对于每月订购,您可能会考虑LAST_DAY()函数 – sorting将在月份的最后一天,但这应该相当于在该月的第一天sorting…不应该吗?

上面接受的答案对我来说并不奏效,因为它按字母顺序排列了几个星期,而不是按照时间顺序:

 2012/1 2012/10 2012/11 ... 2012/19 2012/2 

这是我的解决scheme,按周计算和分组:

 SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name, YEAR(date), WEEK(date), COUNT(*) FROM column_name GROUP BY week_name ORDER BY YEAR(DATE) ASC, WEEK(date) ASC 

产生:

 YEAR/WEEK YEAR WEEK COUNT 2011/51 2011 51 15 2011/52 2011 52 14 2012/1 2012 1 20 2012/2 2012 2 14 2012/3 2012 3 19 2012/4 2012 4 19 

算出来…这有点麻烦,但在这里。

 FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7)) 

而且,如果您的业务规则说明星期一开始,则将-1更改为-2


编辑

多年过去了,我终于开始写这个了。 http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

只是在select这个广告:

 DATE_FORMAT($yourDate, \'%X %V\') as week 

 group_by(week); 

如果您需要“星期结束”date,这也将工作。 这将计算每周的logging数。 示例:如果在2010年1月1日至2010年1月8日(含)之间创build了三个工单,并且在2010年1月9日至2010年1月16日(含)之间创build了5个工单,则返回:

3 1/8/2010
5 1/16/2010

我不得不使用额外的DATE()函数来截断我的date时间字段。

SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending FROM work_order wo GROUP BY week_ending;

Interesting Posts