4. 使用DISTINCT统计不重复部门列表
任务说明
员工表 employees 中同一部门会出现多次(每个员工一行)。本节要回答两个问题:一是如何用 DISTINCT 取出所有不重复的部门名称;二是验证 DISTINCT 与 GROUP BY 在“去重结果”上是否一致。示例使用如下表结构与数据(教学示例数据,非真实业务数据):
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(20),
department VARCHAR(20),
salary DECIMAL(8,2),
hire_date DATE
);
INSERT INTO employees VALUES
(1,'张伟','研发部',18000,'2020-03-01'),
(2,'李娜','研发部',16500,'2021-07-15'),
(3,'王强','市场部',12000,'2019-11-20'),
(4,'赵敏','市场部',13500,'2022-01-05'),
(5,'陈杰','财务部',11000,'2020-09-10'),
(6,'刘洋','研发部',21000,'2018-05-22'),
(7,'孙丽','人事部', 9500,'2021-02-18'),
(8,'周涛','市场部',12800,'2023-04-01'),
(9,'吴静','财务部',10500,'2022-08-30'),
(10,'郑凯','人事部', 9800,'2023-06-12');
DISTINCT 去重写法
DISTINCT 作用于 SELECT 的结果集,对整行组合去重。单列去重时,它等价于“把该列所有出现过的值各保留一次”。
SELECT DISTINCT department
FROM employees
ORDER BY department;
预期结果(5 个不重复部门,按名称排序):
| department |
|---|
| 人事部 |
| 市场部 |
| 研发部 |
| 财务部 |
注意:上表按数据库默认排序规则展示,实际顺序取决于 ORDER BY 与字符集排序规则;若使用中文排序,结果顺序可能不同,但“不重复部门集合”本身不变。
GROUP BY 去重写法
用 GROUP BY 把相同部门归为一组,每组只输出一行,同样得到不重复部门列表:
SELECT department
FROM employees
GROUP BY department
ORDER BY department;
一致性验证
要证明两种写法结果一致,不能只看“看起来一样”,而应做集合层面的比较。下面用 EXCEPT 双向差集验证:若两个方向都返回 0 行,则两个结果集完全相同。
-- 方向一:DISTINCT 有而 GROUP BY 没有的部门
SELECT DISTINCT department FROM employees
EXCEPT
SELECT department FROM employees GROUP BY department;
-- 方向二:GROUP BY 有而 DISTINCT 没有的部门
SELECT department FROM employees GROUP BY department
EXCEPT
SELECT DISTINCT department FROM employees;
两个查询都返回空结果集,说明 DISTINCT department 与 GROUP BY department 在本例数据上去重结果一致。若某数据库不支持 EXCEPT,可改用 NOT IN 或 LEFT JOIN ... IS NULL 做等价验证。
关键区别:DISTINCT 只做去重,不能直接对分组做聚合;GROUP BY 是分组机制,分组后可以配合 COUNT、AVG、HAVING 等做统计与过滤。仅当“只取不重复值”时,两者结果一致。
易错点:SELECT DISTINCT department, salary 去重的是“部门+薪资”整行组合,不是只对部门去重。若只想按部门去重,SELECT 列表中不要混入其他列。
结果判读与验证要点
- 行数判读:去重结果应为 4 行(人事部、市场部、研发部、财务部)。若返回 10 行,说明
DISTINCT未生效或写成了SELECT department。 - 一致性判读:两个
EXCEPT查询都返回空集,才可判定两种写法结果一致;任一方向有行,说明结果集存在差异。 - 排序影响:
ORDER BY只影响展示顺序,不影响去重集合;验证一致性时不要依赖默认顺序。 - NULL 处理:若部门列存在
NULL,DISTINCT与GROUP BY都会把NULL视为一个独立分组值,结果仍一致,但需在业务上确认是否要排除NULL。