Mysql 按x分组与不同分组(x)

Mysql 按x分组与不同分组(x),mysql,group-by,distinct,Mysql,Group By,Distinct,如果我有一个具有重复id的表,如果我使用按id分组,就像我使用选择不同的(id),我将得到相同的结果,对吗 那么,什么时候我应该选择一个选项而不是另一个呢?一个DISTINCT and GROUP BY通常会生成相同的查询计划,因此两个查询构造的性能应该是相同的。应使用GROUP BY将聚合运算符应用于每个组。如果您只需要删除重复项,则使用DISTINCT。如果您使用子查询,则该查询的执行计划会有所不同,因此在这种情况下,您需要在决定哪个执行计划更快之前检查执行计划 Example of DIS

如果我有一个具有重复id的表,如果我使用
按id分组
,就像我使用
选择不同的(id)
,我将得到相同的结果,对吗


那么,什么时候我应该选择一个选项而不是另一个呢?

一个DISTINCT and GROUP BY通常会生成相同的查询计划,因此两个查询构造的性能应该是相同的。应使用GROUP BY将聚合运算符应用于每个组。如果您只需要删除重复项,则使用DISTINCT。如果您使用子查询,则该查询的执行计划会有所不同,因此在这种情况下,您需要在决定哪个执行计划更快之前检查执行计划

Example of DISTINCT:
 SELECT DISTINCT Employee, Rank
 FROM Employees

Example of GROUP BY:
 SELECT Employee, Rank
 FROM Employees
 GROUP BY Employee, Rank

Example of GROUP BY with aggregate function:
 SELECT Employee, Rank, COUNT(*) EmployeeCount
 FROM Employees
 GROUP BY Employee, Rank 

参考:Pinal Dave()

一个DISTINCT and GROUP BY通常生成相同的查询计划,因此两个查询构造的性能应该相同。应使用GROUP BY将聚合运算符应用于每个组。如果您只需要删除重复项,则使用DISTINCT。如果您使用子查询,则该查询的执行计划会有所不同,因此在这种情况下,您需要在决定哪个执行计划更快之前检查执行计划

Example of DISTINCT:
 SELECT DISTINCT Employee, Rank
 FROM Employees

Example of GROUP BY:
 SELECT Employee, Rank
 FROM Employees
 GROUP BY Employee, Rank

Example of GROUP BY with aggregate function:
 SELECT Employee, Rank, COUNT(*) EmployeeCount
 FROM Employees
 GROUP BY Employee, Rank 

参考:Pinal Dave()

如果需要聚合函数,如
SUM
MAX
等,则应使用
groupby

如果只需要对列进行分组,则它们是相同的(并且使用相同的计划)

请注意,
DISTINCT
不是一个函数,因此本条款:

SELECT DISTINCT(id), othercol
这与相同(列顺序除外)

或者只是

SELECT DISTINCT othercol, id

如果存在具有相同的
id
但不同的
othercol
的记录,则仍可能在
id
上为您提供重复项。如果您需要聚合函数,如
SUM
MAX
等,则应使用
GROUP BY

如果只需要对列进行分组,则它们是相同的(并且使用相同的计划)

请注意,
DISTINCT
不是一个函数,因此本条款:

SELECT DISTINCT(id), othercol
这与相同(列顺序除外)

或者只是

SELECT DISTINCT othercol, id

如果存在具有相同
id
但不同
othercol
的记录,则仍可能在
id
上为您提供重复项,只需提供额外信息:

如果查询的是索引字段且有限制,最好使用GROUP BY而不是DISTINCT,因为它将使用索引,而不是临时表

请参阅以下链接:

  • 如果存在ORDER BY子句和其他GROUP BY子句,或者ORDER BY或GROUP BY包含联接队列中第一个表以外的表中的列,则会创建一个临时表


例如:

MariaDB [my_db]> EXPLAIN SELECT DISTINCT p.data_prefix FROM my_table p;
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]> EXPLAIN SELECT DISTINCT p.data_prefix FROM my_table p limit 0,40;
+------+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                                     |
+------+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by; Using temporary |
+------+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]> EXPLAIN SELECT p.data_prefix FROM my_table p group by p.data_prefix;
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]> EXPLAIN SELECT p.data_prefix FROM my_table p group by p.data_prefix limit 0,40;
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]>

仅提供额外信息:

如果查询的是索引字段且有限制,最好使用GROUP BY而不是DISTINCT,因为它将使用索引,而不是临时表

请参阅以下链接:

  • 如果存在ORDER BY子句和其他GROUP BY子句,或者ORDER BY或GROUP BY包含联接队列中第一个表以外的表中的列,则会创建一个临时表


例如:

MariaDB [my_db]> EXPLAIN SELECT DISTINCT p.data_prefix FROM my_table p;
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]> EXPLAIN SELECT DISTINCT p.data_prefix FROM my_table p limit 0,40;
+------+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                                     |
+------+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by; Using temporary |
+------+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]> EXPLAIN SELECT p.data_prefix FROM my_table p group by p.data_prefix;
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]> EXPLAIN SELECT p.data_prefix FROM my_table p group by p.data_prefix limit 0,40;
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
|    1 | SIMPLE      | p     | range | NULL          | data_prefix | 33      | NULL |   18 | Using index for group-by |
+------+-------------+-------+-------+---------------+------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [my_db]>

您可能更喜欢
分组方式
而不是
不同方式
的示例。考虑一个场景,其中需要在不同的结果集上应用<代码>窗口函数< /> >(<强>不一定是Ro.No())。根据操作顺序,您必须使用
distinct

select id, row_number() over (order by id) as rn
from (select distinct id from my_table) t;
使用
groupby

select id, row_number() over (order by id) as rn 
from my_table
group by id;

这是可能的,因为
窗口函数
是在
分组依据
之后但在
不同
之前应用的,这是一个您可能更喜欢
分组依据
而不是
不同
的示例。考虑一个场景,其中需要在不同的结果集上应用<代码>窗口函数< /> >(<强>不一定是Ro.No())。根据操作顺序,您必须使用
distinct

select id, row_number() over (order by id) as rn
from (select distinct id from my_table) t;
使用
groupby

select id, row_number() over (order by id) as rn 
from my_table
group by id;

这是可能的,因为
窗口函数
是在
分组依据
之后但在
不同

之前应用的。如果存在具有相同id但不同othercol“+1的记录,则可能仍会在id上给您重复项
DISTINCT
意味着行本身是唯一的,这意味着所有返回列的组合。所以我的前提是groupby和DISTINCT返回相同的结果,不是完全准确的吗?如果我理解正确,DISTINCT返回唯一的行,但GROUP BY返回按特定字段折叠的行。。尽管在比较简单查询时,这通常看起来是相同的。很高兴知道-谢谢。“如果有相同id但不同othercol“+1”的记录,可能仍然会在id上给您重复的
DISTINCT
意味着行本身是唯一的,这意味着所有返回列的组合。所以我的前提是groupby和DISTINCT返回相同的结果,不是完全准确的吗?如果我理解正确,DISTINCT返回唯一的行,但GROUP BY返回按特定字段折叠的行。。尽管在比较简单查询时,这通常看起来是相同的。很好知道-谢谢。没有必要将列和/或表达式包装在括号中;
DISTINCT
关键字应用于整个选择列表。
id
周围的参数不会影响查询结果或执行计划。
groupby
更一般
distinct
实际上只是一种速记。真正需要它的唯一时间是当您执行
选择distinct*
时,因为不允许使用
group by*
。换言之,首先关注学习和使用
group by
。。。。虽然DISTINCT*看起来毫无意义@在没有任何伤害的情况下,一般都要保持冷静