标题: mysql group by 的 奇怪地方? 是bug 还是它的特性 [打印本页] 作者: carcase 时间: 2009-6-18 10:08 标题: mysql group by 的 奇怪地方? 是bug 还是它的特性 Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7397 to server version: 5.1.31
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> use nowhill;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
mysql> insert into test(1,1,1),(1,1,2),(1,1,3),(1,2,5),(1,2,1),(1,2,6);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1,1),(1,1,2),(1,1,3),(1,2,5),(1,2,1),(1,2,6)' at line 1
mysql> insert into test values(1,1,1),(1,1,2),(1,1,3),(1,2,5),(1,2,1),(1,2,6);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select a,b,c from test group by a,b;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 1 | 1 |
| 1 | 2 | 5 |
+------+------+------+
2 rows in set (0.00 sec)
mysql> select * from (select a,b,c from test order by a,b,c) group by a,b;
ERROR 1248 (42000): Every derived table must have its own alias
mysql> select * from (select a,b,c from test order by a,b,c) b group by a,b;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 1 | 1 |
| 1 | 2 | 1 |
+------+------+------+
2 rows in set (0.00 sec)
select * from (select a,b,c from test order by a,b,c) b group by a,b;
这样的sql 在orace 下是行不通的
但是 在mysql 下 起到了 意向不到的效果
相当得到了 a,b两列 分组后 的 c的 最小值 ,如果 排序相反,还可以得到最大值,
如:
mysql> select * from (select a,b,c from test order by a,b,c desc) b group by a,b;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 1 | 3 |
| 1 | 2 | 6 |
+------+------+------+
2 rows in set (0.00 sec)
mysql> select * from (select a,b,c,d from test order by a,b,c) t group by a,b; 得到了最小值和最小值时的时间
+------+------+------+---------------------+
| a | b | c | d |
+------+------+------+---------------------+
| 1 | 1 | 1 | 2009-06-22 15:04:55 |
| 1 | 2 | 1 | 2009-06-22 15:05:47 |
+------+------+------+---------------------+
2 rows in set (0.00 sec)
mysql> select * from (select a,b,c,d from test order by a,b,c desc) t group by a,b; 得到了最大值 和最大值的时间
+------+------+------+---------------------+
| a | b | c | d |
+------+------+------+---------------------+
| 1 | 1 | 3 | 2009-06-22 15:05:16 |
| 1 | 2 | 6 | 2009-06-22 15:06:06 |
+------+------+------+---------------------+
2 rows in set (0.00 sec)
虽然方法有点土 ,的确实现了这个功能;
不知这种方法效率如何
相比以下的方法:
mysql> select * from test where (a,b,c) in(select a,b,min(c) from test group by a,b); 取得最小值 和最小值的时间
+------+------+------+---------------------+
| a | b | c | d |
+------+------+------+---------------------+
| 1 | 1 | 1 | 2009-06-22 15:04:55 |
| 1 | 2 | 1 | 2009-06-22 15:05:47 |
+------+------+------+---------------------+
2 rows in set (0.00 sec)
mysql> select * from test where (a,b,c) in(select a,b,max(c) from test group by a,b); 得到了最大值 和最大值的时间
+------+------+------+---------------------+
| a | b | c | d |
+------+------+------+---------------------+
| 1 | 1 | 3 | 2009-06-22 15:05:16 |
| 1 | 2 | 6 | 2009-06-22 15:06:06 |
+------+------+------+---------------------+
方法如下:
mysql> select t1.a,
-> t1.b,
-> t1.c '最小值',
-> t1.d '取得最小值的时间',
-> t2.c '最大值',
-> t2.d '取得最大值的时间'
-> from
-> (select a,b,c,d from (select a,b,c,d from test order by a,b,c) t group by a,b) t1,
-> (select a,b,c,d from (select a,b,c,d from test order by a,b,c desc) t group by a,b) t2
-> where t1.a = t2.a
-> and t1.b = t2.b;
+------+------+--------+---------------------+--------+---------------------+
| a | b | 最小值 | 取得最小值的时间 | 最大值 | 取得最大值的时间 |
+------+------+--------+---------------------+--------+---------------------+
| 1 | 1 | 1 | 2009-06-22 15:04:55 | 3 | 2009-06-22 15:05:16 |
| 1 | 2 | 1 | 2009-06-22 15:05:47 | 6 | 2009-06-22 15:06:06 |
+------+------+--------+---------------------+--------+---------------------+
2 rows in set (0.00 sec)
mysql> select t1.a,
-> t1.b,
-> t1.c '最小值',
-> t1.d '取得最小值的时间',
-> t2.c '最大值',
-> t2.d '取得最大值的时间'
-> from (select a, b, c, d from test where (a, b, c) in (select a, b, min(c) from test group by a, b)) t1,
-> (select a, b, c, d from test where (a, b, c) in (select a, b, max(c) from test group by a, b)) t2
-> where t1.a = t2.a
-> and t1.b = t2.b;
+------+------+--------+---------------------+--------+---------------------+
| a | b | 最小值 | 取得最小值的时间 | 最大值 | 取得最大值的时间 |
+------+------+--------+---------------------+--------+---------------------+
| 1 | 1 | 1 | 2009-06-22 15:04:55 | 3 | 2009-06-22 15:05:16 |
| 1 | 2 | 1 | 2009-06-22 15:05:47 | 6 | 2009-06-22 15:06:06 |
+------+------+--------+---------------------+--------+---------------------+
2 rows in set (0.00 sec)
看了一下执行计划
mysql> explain
-> select t1.a,
-> t1.b,
-> t1.c '最小值',
-> t1.d '取得最小值的时间',
-> t2.c '最大值',
-> t2.d '取得最大值的时间'
-> from (select a, b, c, d from test where (a, b, c) in (select a, b, min(c) from test group by a, b)) t1,
-> (select a, b, c, d from test where (a, b, c) in (select a, b, max(c) from test group by a, b)) t2
-> where t1.a = t2.a
-> and t1.b = t2.b;
+----+--------------------+------------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+------+---------------+------+---------+------+------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | |
| 1 | PRIMARY | <derived4> | ALL | NULL | NULL | NULL | NULL | 2 | Using where; Using join buffer |
| 4 | DERIVED | test | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
| 5 | DEPENDENT SUBQUERY | test | ALL | NULL | NULL | NULL | NULL | 6 | Using temporary; Using filesort |
| 2 | DERIVED | test | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
| 3 | DEPENDENT SUBQUERY | test | ALL | NULL | NULL | NULL | NULL | 6 | Using temporary; Using filesort |
+----+--------------------+------------+------+---------------+------+---------+------+------+---------------------------------+
6 rows in set (0.01 sec)
mysql> explain
-> select t1.a,
-> t1.b,
-> t1.c '最小值',
-> t1.d '取得最小值的时间',
-> t2.c '最大值',
-> t2.d '取得最大值的时间'
-> from
-> (select a,b,c,d from (select a,b,c,d from test order by a,b,c) t group by a,b) t1,
-> (select a,b,c,d from (select a,b,c,d from test order by a,b,c desc) t group by a,b) t2
-> where t1.a = t2.a
-> and t1.b = t2.b;
+----+-------------+------------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | |
| 1 | PRIMARY | <derived4> | ALL | NULL | NULL | NULL | NULL | 2 | Using where; Using join buffer |
| 4 | DERIVED | <derived5> | ALL | NULL | NULL | NULL | NULL | 6 | Using temporary; Using filesort |
| 5 | DERIVED | test | ALL | NULL | NULL | NULL | NULL | 6 | Using filesort |
| 2 | DERIVED | <derived3> | ALL | NULL | NULL | NULL | NULL | 6 | Using temporary; Using filesort |
| 3 | DERIVED | test | ALL | NULL | NULL | NULL | NULL | 6 | Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+------+---------------------------------+
6 rows in set (0.00 sec)