如何在MySQL中按周分组?

O. *_*nes 76 mysql datetime data-migration group-by dayofweek

Oracle的表服务器提供内置函数TRUNC(timestamp,'DY').此函数将上一个星期日的任何时间戳转换为午夜.在MySQL中执行此操作的最佳方法是什么?

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

TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))
Run Code Online (Sandbox Code Playgroud)

但这个DATE_FORMAT技巧几周不会奏效.我知道这个WEEK(timestamp)功能,但我真的不想要一年内的周数; 这个东西是多年的工作.

mjv*_*mjv 105

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

不是太优雅,但功能......

当然,您也可以将这两个日期部分组合在一个表达式中,例如

SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc...
FROM ...
WHERE ..
GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))
Run Code Online (Sandbox Code Playgroud)

编辑:正如Martin xx所指出的那样,你也可以使用这个YEARWEEK(mysqldatefield)功能,虽然它的输出不如上面较长的公式那样友好.

编辑2 [3年半后!]:
YEARWEEK(mysqldatefield)使用可选的第二个参数(mode)设置为0或2可能是由聚集的最佳途径完整周(即包括针对跨年度1月1日周),如果是什么是期望的.YEAR() / WEEK()最初在这个答案中提出的方法具有将这种"跨界"周的汇总数据分成两部分的效果:一年与前一年,一年与新年.
每年都要采用简洁的方式,最多需要两个部分周,一个是两端,通常需要会计等等.为此,YEAR() / WEEK()方法更好.

  • `YEARWEEK()`会产生一个`INT(6)`,我认为它可以更快地排序/加入/分组 (11认同)
  • @mjv:当两年共享同一周时会发生什么?喜欢这个 31-12-2012 到 6-1-2013(周一到周日)。有什么解决办法吗? (2认同)

O. *_*nes 31

想出来......它有点麻烦,但在这里.

FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7))
Run Code Online (Sandbox Code Playgroud)

而且,如果您的业务规则表明您的周数从星期一开始,请更改-1-2.


编辑

几年过去了,我终于开始写这篇文章了. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/


B S*_*ven 27

上面接受的答案对我不起作用,因为它按字母顺序排序了几周,而不是按时间顺序排列:

2012/1
2012/10
2012/11
...
2012/19
2012/2
Run Code Online (Sandbox Code Playgroud)

这是我按周计算和分组的解决方案:

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
Run Code Online (Sandbox Code Playgroud)

产生:

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
Run Code Online (Sandbox Code Playgroud)

  • 按日期排序(`ORDER BY date ASC`)也可以解决问题 (2认同)

mar*_*ton 22

您可以使用YEARWEEK()函数获取连接的年份和周数(200945).如果我正确理解了您的目标,那么您应该可以对多年数据进行分组.

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

DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY )
Run Code Online (Sandbox Code Playgroud)

对于每月订购,您可能会考虑LAST_DAY()函数 - 排序将在该月的最后一天,但这相当于按月的第一天排序...不应该吗?