问题:为什么在以下示例中使用GROUP BY HOUR(timestamp)函数进行查询会返回usercount timestamp @ 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)
这是常规查询的结果(没有分组):
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)
注意:id列是AUTO INC + index
答案 0 :(得分:1)
不确定的将返回行。 MySQL可以自由地从组中的任何行返回值。
其他数据库会抛出这样的查询异常。但MySQL扩展了功能,并允许SELECT列表中的非聚合。
此处记录了此行为:http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html
MySQL扩展了
GROUP BY
的使用,以便选择列表可以引用未在GROUP BY
子句中命名的非聚合列。这意味着前面的查询在MySQL中是合法的。您可以通过避免不必要的列排序和分组来使用此功能来获得更好的性能。但是,当GROUP BY中未命名的每个非聚合列中的所有值对于每个组都相同时,这非常有用。服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。此外,添加ORDER BY
子句不会影响每个组中值的选择。选择值后会对结果集进行排序,ORDER BY
不会影响服务器选择的每个组中的值。
答案 1 :(得分:0)
为了Q / A的完整性,我将在这里重复我在评论部分已经注意到的内容:id列(AUTO INC)是唯一的(索引),并且在选择时间戳代表时似乎也会考虑到值。显然,最低的第一列id值分布在不同的日期,但相同的小时,总是“赢”作为组中选定的时间戳值。