1

我目前使用以下查询来获取按天分组的数据:

SELECT DATE(from_unixtime(timestampcolumn)) as date, COUNT(*)
FROM db.table
WHERE timestampcolumn BETWEEN :startTime AND :endTime
GROUP BY DATE(from_unixtime(timestampcolumn))
ORDER BY timestampcolumn

DATE()函数返回字符串YYYY-MM-DD,所以上面的查询很简单,非常适合获取按天分组的数据,但是如何修改它以返回按周分组的数据?


回应乔纳森的回答:

我尝试在 SQL Fiddle 中创建一个示例,但由于DATE()某种原因 SQL 函数在 SQL Fiddle 中不起作用(它在 SQL Fiddle 中根本不起作用,但在我的 live 和 wamp 服务器上都起作用)。

因此,如果您愿意,可以尝试以下示例:

设置:

CREATE TABLE example(id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), timestamp INT, data INT);

INSERT INTO example (timestamp, data) VALUES (1355400000, 1);
INSERT INTO example (timestamp, data) VALUES (1355659200, 1);
INSERT INTO example (timestamp, data) VALUES (1357694861, 1);
INSERT INTO example (timestamp, data) VALUES (1355918400, 1);
INSERT INTO example (timestamp, data) VALUES (1356955200, 1);
INSERT INTO example (timestamp, data) VALUES (1358510400, 1);
INSERT INTO example (timestamp, data) VALUES (1358769600, 1);
INSERT INTO example (timestamp, data) VALUES (1358769600, 1);
INSERT INTO example (timestamp, data) VALUES (1371824368, 1);
INSERT INTO example (timestamp, data) VALUES (1371833476, 1);
INSERT INTO example (timestamp, data) VALUES (1371840324, 1);
INSERT INTO example (timestamp, data) VALUES (1371850523, 1);
INSERT INTO example (timestamp, data) VALUES (1371863191, 1);
INSERT INTO example (timestamp, data) VALUES (1371865401, 1);
INSERT INTO example (timestamp, data) VALUES (1371872379, 1);
INSERT INTO example (timestamp, data) VALUES (1372006190, 1);
INSERT INTO example (timestamp, data) VALUES (1372051945, 1);
INSERT INTO example (timestamp, data) VALUES (1372189402, 1);
INSERT INTO example (timestamp, data) VALUES (1372207830, 1);
INSERT INTO example (timestamp, data) VALUES (1372229733, 1);
INSERT INTO example (timestamp, data) VALUES (1372350338, 1);
INSERT INTO example (timestamp, data) VALUES (1372358259, 1);

询问:

SELECT DATE(from_unixtime(timestamp)) as date, COUNT(*)
FROM example
WHERE timestamp BETWEEN 0 AND 9999999999999999999999999999999
GROUP BY DATE(from_unixtime(timestamp))
ORDER BY timestamp

输出:

2012-12-13  1
2012-12-16  1
2012-12-19  1
2012-12-31  1
2013-01-08  1
2013-01-18  1
2013-01-21  2
2013-06-21  7
2013-06-23  1
2013-06-24  1
2013-06-25  2
2013-06-26  1
2013-06-27  2

现在,将时间戳除以(7 * 24 * 3600).

询问:

SELECT DATE(from_unixtime(timestamp / (7 * 24 * 3600))) as date, COUNT(*)
FROM example
WHERE timestamp BETWEEN 0 AND 9999999999999999999999999999999
GROUP BY DATE(from_unixtime(timestamp / (7 * 24 * 3600)))
ORDER BY timestamp

输出:

1969-12-31  22
4

3 回答 3

3

一个基本的想法应该是按时间戳的整数值除以一周中的秒数进行分组:timestampcolumn / (7 * 24 * 3600)

然后,您需要考虑边缘效应和时区:

  • 是 1970-01-01 在一周中的适当日子(那是星期四,所以可能不是)。
  • 给定数据的一周究竟是什么时候开始的;它受冬季和夏季时间(标准和夏令时)的影响吗?

您可以通过在划分之前向时间戳列添加适当的值来处理这些问题。最后一个转折:一些系统可能会补偿闰秒。POSIX 没有。你必须决定这对你是否重要。

另一个需要考虑的选项是是否有办法将日期格式化为周值(例如 ISO 8601 表示法,例如 2013-W23 表示 2013 年第 23 周)。然后,您可以简单地按该字符串分组。


这就是我的意思:

SELECT timestamp / (7 * 24 * 3600) AS weekno, COUNT(*)
  FROM example
 WHERE timestamp BETWEEN 0 AND 9999999999999999999999999999999
 GROUP BY timestamp / (7 * 24 * 3600)
 ORDER BY weekno

您可能可以使用GROUP BY weekno,或者您可能必须使用ORDER BY timestamp / (7 * 24 * 3600),但您制造了周数。如果您还需要生成日期,那么您可以使用:

SELECT timestamp / (7 * 24 * 3600) AS weekno,
       DATE(FROM_UNIXTIME((7 * 24 * 3600) * INT(timestamp / (7 * 24 * 3600))))) AS weekstart,
       COUNT(*)
  FROM example
 WHERE timestamp BETWEEN 0 AND 9999999999999999999999999999999
 GROUP BY timestamp / (7 * 24 * 3600)
 ORDER BY weekno

您可能也可以使用MIN(DATE(FROM_UNIXTIME(timestamp)))for weekstart,除非您认为一周的第一天不会总是在数据中表示。

于 2013-06-27T20:05:55.193 回答
1

您不能只使用原始查询并使用 WEEK 函数而不是 DAY() 吗?

GROUP BY WEEK(from_unixtime(timestampcolumn))
于 2016-10-12T21:25:42.273 回答
0

这是基于上述建议的干净,经过测试的解决方案:

SELECT  WEEK(from_unixtime(timestamp)) AS week_no, 
        date(from_unixtime(timestamp)) as week_start, 
        COUNT(*) as row_count
FROM api_tracker
GROUP BY WEEK(from_unixtime(timestamp))
ORDER BY week_no DESC

SQL 响应:

结果

感谢Shane NJonathan Leffler

于 2020-06-03T06:41:50.653 回答