Mysql 为什么按小时分组(时间戳)返回特定的时间戳?

Mysql 为什么按小时分组(时间戳)返回特定的时间戳?,mysql,group-by,hour,Mysql,Group By,Hour,问题:为什么以下示例中使用按小时分组(时间戳)函数的查询返回usercount时间戳@2015-02-18 23:16:25,而不是第一次出现@2015-02-18 23:14:12 MySQL内部决定这种选择的机制是什么 以下是按小时分组查询的结果: mysql> SELECT *, COUNT(user_id) AS usercount FROM table_log WHERE user_id = 1 GROUP BY HOUR(timestamp) ORDER BY timesta

问题:为什么以下示例中使用按小时分组(时间戳)函数的查询返回usercount时间戳@2015-02-18 23:16:25,而不是第一次出现@2015-02-18 23:14:12

MySQL内部决定这种选择的机制是什么


以下是按小时分组查询的结果:

mysql> SELECT *, COUNT(user_id) AS usercount FROM table_log WHERE user_id = 1 GROUP BY HOUR(timestamp) ORDER BY timestamp,usercount DESC;

+------+---------+-----------+---------------------+-----------+
| id   | user_id | user_name | timestamp           | usercount |
+------+---------+-----------+---------------------+-----------+
| 1013 | 1       | 1         | 2015-02-16 00:51:32 |         2 |
| 1016 | 1       | 1         | 2015-02-16 21:38:52 |         2 |
| 1018 | 1       | 1         | 2015-02-17 02:05:44 |         3 |
| 1022 | 1       | 1         | 2015-02-18 04:51:22 |         8 |
| 1001 | 1       | 1         | 2015-02-18 23:16:25 |        22 |
| 1005 | 1       | 1         | 2015-02-19 03:06:01 |         5 |
| 1009 | 1       | 1         | 2015-02-19 05:15:32 |         3 |
| 1011 | 1       | 1         | 2015-02-19 11:57:26 |         1 |
| 1012 | 1       | 1         | 2015-02-19 12:09:20 |         1 |
+------+---------+-----------+---------------------+-----------+
9 rows in set (0.01 sec)
下面是常规查询的结果(无分组):

注意:id列是AUTO INC+index

它不确定返回哪一行。MySQL可以自由地从组中的任何行返回值

其他数据库将抛出这样一个查询的异常。但是MySQL扩展了该功能,并允许在选择列表中使用非聚合

行为记录如下:

MySQL扩展了
GROUPBY
的使用,因此select列表可以引用
GROUPBY
子句中未命名的未聚合列。这意味着前面的查询在MySQL中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要是在GROUP BY中未命名的每个未聚合列中的所有值对于每个组都相同时才有用。服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的。此外,不能通过添加
ORDER by
子句来影响每组值的选择。结果集的排序发生在选择值之后,并且
orderby
不会影响服务器在每个组中选择的值


对于Q/A的完整性,我将在这里重复我在评论部分已经注意到的内容:id列(AUTO INC)是唯一的(索引),并且在选择时间戳代表值时似乎也要考虑到这一点。显然,最低的第一列id值分布在不同的日期,但在相同的时间,作为组中选择的时间戳值总是“赢”的。

是唯一的id列(最低索引优先)?因为组中有多个值,它随机抽出一个值作为组的代表。标准SQL甚至不允许您这样做。如果要检索最早的时间戳,需要说MIN(timestamp)。还要注意,HOUR()将返回一个从0到23的值。因此,当您的数据在多天内传播时,它仍然会落在24个不同的存储桶中的一个。谢谢shawnt00,不知道MIN()函数Hi spencer7593,我接受您的回答,但我也分析了数据(在更大的范围内),似乎列id(AUTO INC)考虑到-始终使用最低索引值作为代表。谢谢@dev101:这可能是您观察到的行为,但这种行为不能保证。我认为影响行为的并不是AUTO_INCREMENT属性,而是MySQL检索行的顺序。。。这实际上取决于使用什么索引。。。对于InnoDB表,主键或唯一索引用作集群键。很可能,AUTO_INCREMENT列是主键。如果MySQL使用不同的索引来访问这些行,那么很可能使用索引中的“第一”行(对于组)。但是再一次…@dev101:。。。这种行为不能保证。如果需要特定行,请使用聚合表达式。。。要获得最低值,例如使用
MIN()
。如果
sql\u mode
只包含
完整的\u GROUP\u BY
,那么MySQL将像其他数据库一样,拒绝在选择列表中包含非聚合的查询,这些查询也不会出现在
GROUP BY
子句中。谢谢spencer7593,列
id
也是主键,因此可能就是主键。我没有意识到关键参数在这种情况下是重要的,会包括在原始问题中。在这个特定的查询中,如何在GROUP BY HOUR()中使用MIN()?如果应用于时间戳,显然它会为所有内容返回单个时间戳。
自动增量
根本不是一个因素。。。除了MySQL恰好要求自动递增的列必须在索引中。观察到的行为是由于MySQL检索行的顺序。。。在这个特定的例子中,MySQL碰巧使用了一个特定的索引,很可能表是InnoDB,auto_increment列是主键。为了答案的完整性,我们应该真正指出,从这个特定案例中得出的推论/结论并不适用于更一般的案例。
mysql> SELECT * FROM table_log WHERE user_id = 1 ORDER BY timestamp;

+------+---------+-----------+---------------------+
| id   | user_id | user_name | timestamp           |
+------+---------+-----------+---------------------+
| 1013 | 1       | 1         | 2015-02-16 00:51:32 |
| 1014 | 1       | 1         | 2015-02-16 00:51:38 |
| 1015 | 1       | 1         | 2015-02-16 03:12:28 |
| 1016 | 1       | 1         | 2015-02-16 21:38:52 |
| 1017 | 1       | 1         | 2015-02-16 21:39:33 |
| 1018 | 1       | 1         | 2015-02-17 02:05:44 |
| 1019 | 1       | 1         | 2015-02-17 02:05:52 |
| 1020 | 1       | 1         | 2015-02-17 02:05:55 |
| 1021 | 1       | 1         | 2015-02-17 05:21:19 |
| 1022 | 1       | 1         | 2015-02-18 04:51:22 |
| 1023 | 1       | 1         | 2015-02-18 04:51:31 |
| 1024 | 1       | 1         | 2015-02-18 04:51:35 |
| 1025 | 1       | 1         | 2015-02-18 04:51:43 |
| 1026 | 1       | 1         | 2015-02-18 04:51:46 |
| 1027 | 1       | 1         | 2015-02-18 04:52:10 |
| 1028 | 1       | 1         | 2015-02-18 04:52:24 |
| 1029 | 1       | 1         | 2015-02-18 04:52:31 |
| 1030 | 1       | 1         | 2015-02-18 23:14:12 |
| 1031 | 1       | 1         | 2015-02-18 23:14:16 |
| 1032 | 1       | 1         | 2015-02-18 23:14:53 |
| 1033 | 1       | 1         | 2015-02-18 23:14:57 |
| 1034 | 1       | 1         | 2015-02-18 23:14:59 |
| 1035 | 1       | 1         | 2015-02-18 23:15:02 |
| 1036 | 1       | 1         | 2015-02-18 23:15:05 |
| 1037 | 1       | 1         | 2015-02-18 23:15:08 |
| 1038 | 1       | 1         | 2015-02-18 23:15:10 |
| 1039 | 1       | 1         | 2015-02-18 23:15:12 |
| 1040 | 1       | 1         | 2015-02-18 23:15:13 |
| 1041 | 1       | 1         | 2015-02-18 23:15:14 |
| 1042 | 1       | 1         | 2015-02-18 23:15:24 |
| 1043 | 1       | 1         | 2015-02-18 23:15:29 |
| 1044 | 1       | 1         | 2015-02-18 23:15:39 |
| 1045 | 1       | 1         | 2015-02-18 23:15:44 |
| 1046 | 1       | 1         | 2015-02-18 23:16:15 |
| 1047 | 1       | 1         | 2015-02-18 23:16:20 |
| 1001 | 1       | 1         | 2015-02-18 23:16:25 |
| 1002 | 1       | 1         | 2015-02-18 23:35:31 |
| 1003 | 1       | 1         | 2015-02-18 23:47:20 |
| 1004 | 1       | 1         | 2015-02-18 23:47:27 |
| 1005 | 1       | 1         | 2015-02-19 03:06:01 |
| 1006 | 1       | 1         | 2015-02-19 03:06:05 |
| 1007 | 1       | 1         | 2015-02-19 03:06:11 |
| 1008 | 1       | 1         | 2015-02-19 03:06:19 |
| 1009 | 1       | 1         | 2015-02-19 05:15:32 |
| 1010 | 1       | 1         | 2015-02-19 05:15:35 |
| 1011 | 1       | 1         | 2015-02-19 11:57:26 |
| 1012 | 1       | 1         | 2015-02-19 12:09:20 |
+------+---------+-----------+---------------------+
47 rows in set (0.01 sec)