建表语句:
drop table if exists `salaries` ;
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
INSERT INTO salaries VALUES(10001,72527,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,43311,'2001-12-01','9999-01-01');
两种处理方法:
- distinct 与 order by 的 结合使用
select distinct salary
from salaries
order by salary desc;
- group by 与 order by 的 结合使用
SELECT salary FROM salaries GROUP BY salary ORDER BY salary desc;
区别:
distinct和group by:
要去重的列数据种类很多时,group by更快
要去重的列数据种类很少时,distinct更快
- 原理分析
DISTINCT
关键字DISTINCT
是用于从查询结果中去除重复行的操作。它会对整个结果集进行扫描,比较每一行与已经扫描过的行是否完全相同。当要去重的列数据种类很少时,它的性能相对较好。例如,如果有一个表students
,其中有id
和name
两列,name
列只有几种不同的值(如 “张三”“李四”“王五”),使用SELECT DISTINCT name FROM students;
时,数据库系统只需要在有限的几种不同的name
值之间进行比较和去重操作。
GROUP BY
子句GROUP BY
主要用于将结果集按照一个或多个列进行分组。在分组的过程中,会自动去除每个组内的重复行。当要去重的列数据种类很多时,GROUP BY
可能会更快。例如,有一个包含大量不同产品名称的销售记录表,使用GROUP BY product_name
进行分组查询,数据库可以利用索引(如果存在合适的索引)或者内部的数据结构来更高效地对数据进行分组和去重。这是因为数据库在执行GROUP BY
操作时,通常会采用更适合处理大量不同数据的算法和数据结构,比如哈希表(Hash Table)来实现分组。
- 性能对比示例(以 MySQL 为例)
- 假设我们有一个表
orders
,包含order_id
、customer_id
和product_id
列。 - 情况一:使用
DISTINCT
且数据种类少- 如果
product_id
只有几种不同的值,比如 10 种不同的产品。查询SELECT DISTINCT product_id FROM orders;
相对比较简单。数据库会遍历结果集,将每个product_id
与之前已经找到的product_id
进行比较,去除重复的。这个过程的时间复杂度在数据种类较少时是可以接受的。
- 如果
- 情况二:使用
GROUP BY
且数据种类多- 假设
customer_id
有大量不同的值(例如 10000 个不同的客户)。查询SELECT customer_id FROM orders GROUP BY customer_id;
。数据库在执行这个GROUP BY
操作时,可能会使用哈希算法来快速地将相同customer_id
的行分到一组。这种方法在处理大量不同的数据时,可能比DISTINCT
逐个比较的方式更高效,因为哈希算法可以在平均情况下以接近常数时间()的复杂度进行插入和查找操作。
- 假设
- 假设我们有一个表
不过,实际的性能还取决于数据库的具体实现、数据量、是否有索引等多种因素。在不同的数据库管理系统(如 Oracle、SQL Server、PostgreSQL 等)中,DISTINCT
和GROUP BY
的性能表现也可能会有所不同。