假设我们有两张表:users (用户信息表) 和 user_projects (用户参与的项目表)。
表1: users
┌─────────┬──────┐
│ user_id │ name │
├─────────┼──────┤
│ 1 │ 张三 │
│ 2 │ 李四 │
└─────────┴──────┘
表2: user_projects
注意,这里为用户'张三'(user_id=1)添加了两条完全相同的'项目A'记录。
┌─────────┬──────────────┐
│ user_id │ project_name │
├─────────┼──────────────┤
│ 1 │ 项目A │
│ 1 │ 项目B │
└─────────┴──────────────┘
| 1 | 项目A | <-- 重复记录
| 2 | 项目C |
- 不使用 DISTINCT 的查询
如果我们想查询用户'张三'(user_id=1)参与了哪些项目,查询语句如下:
1 SELECT
2 u.user_id,
3 u.name,
4 p.project_name
5 FROM
6 users u
7 JOIN
8 user_projects p ON u.user_id = p.user_id
9 WHERE
10 u.user_id = 1;
查询结果 会有3行,因为'张三'在 user_projects 表中有3条记录:
┌─────────┬──────┬──────────────┐
│ user_id │ name │ project_name │
├─────────┼──────┼──────────────┤
│ 1 │ 张三 │ 项目A │
│ 1 │ 张三 │ 项目B │
└─────────┴──────┴──────────────┘
| 1 | 张三 | 项目A | <-- 重复的行
- 使用 DISTINCT 的查询
现在,我们在 SELECT 后面加上 DISTINCT:
1 SELECT DISTINCT
2 u.user_id,
3 u.name,
4 p.project_name
5 FROM
6 users u
7 JOIN
8 user_projects p ON u.user_id = p.user_id
9 WHERE
10 u.user_id = 1;
DISTINCT 会检查每一行所有列的组合 (user_id, name, project_name) 是否唯一。
- 第一行 (1, '张三', '项目A') 是唯一的。
- 第二行 (1, '张三', '项目B') 是唯一的。
- 第三行 (1, '张三', '项目A') 和第一行完全相同,因此它会被 DISTINCT 关键字移除。
最终查询结果 只有2行:
┌─────────┬──────┬──────────────┐
│ user_id │ name │ project_name │
├─────────┼──────┼──────────────┤
│ 1 │ 张三 │ 项目A │
│ 1 │ 张三 │ 项目B │
└─────────┴──────┴──────────────┘
结论
这个例子清晰地表明,DISTINCT 并不是只看某一列(比如 project_name),而是看整行所有列的值组合。只有当多行的所有列的值都完全相同时,DISTINCT 才会将它们视为重复并只保留一行。
DISTINCT 就是为了防止 JOIN 操作后可能出现的、所有选择列都完全相同的重复行,确保最终返回给程序的结果是干净且唯一的。