news 2026/4/30 19:51:03

SQL示例:为什么薪资表需要关联多次

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL示例:为什么薪资表需要关联多次

本文解释了SQL查询中为何需要两次关联薪资表来比较员工和经理的薪资。


核心原因是:一次JOIN只能获取一个人的薪资信息,而查询需要同时获取员工和经理(两个不同个体)的当前薪资进行对比。


通过分步示例说明:第一次关联获取员工薪资,第二次关联获取经理薪资。


文章还指出,若需比较更多角色(如员工、经理、总监),则需相应增加关联次数(如三次)。


这种设计是因为关系型数据库中,JOIN操作基于值匹配,不同角色的薪资需通过独立查询条件获取。


SQL示例:为什么薪资表需要关联两次


题目描述

有一个,部门关系表dept_emp简况如下:

emp_nodept_nofrom_dateto_date
10001d0011986-06-269999-01-01
10002d0011996-08-039999-01-01

有一个部门经理表dept_manager简况如下:

dept_noemp_nofrom_dateto_date
d001100021996-08-039999-01-01

有一个薪水表salaries简况如下:

emp_nosalaryfrom_dateto_date
10001889582002-06-229999-01-01
10002725271996-08-039999-01-01

获取员工其当前的薪水比其manager当前薪水还高的相关信息,

第一列给出员工的emp_no,
第二列给出其manager的manager_no,
第三列给出该员工当前的薪水emp_salary,
第四列给该员工对应的manager当前的薪水manager_salary

select d1.emp_no, d2.emp_no as manager_no, d3.salary as emp_salary, d4.salary as manager_salary from dept_emp d1 join dept_manager d2 on d1.dept_no =d2.dept_no join salaries d3 on d1.emp_no=d3.emp_no join salaries d4 on d2.emp_no=d4.emp_no where d3.salary > d4.salary;

薪资表需要关联两次,是因为我们要获取两种不同角色的当前薪资


核心原因

一次关联只能获取一个人的薪资信息,但我们需要:

  • 员工的薪资(来自salaries表)

  • 经理的薪资(也来自salaries表)

这两个人不同,所以必须分别关联


分步理解

第一次关联 salaries (d3)

sql

JOIN salaries d3 ON d1.emp_no = d3.emp_no
  • d1.emp_no员工编号(如 10001)

  • 关联后,d3.salary取出的是这个员工自己的薪水

第二次关联 salaries (d4)

sql

JOIN salaries d4 ON d2.emp_no = d4.emp_no
  • d2.emp_no经理编号(如 10002)

  • 关联后,d4.salary取出的是这个经理的薪水


直观示例

假设当前已经关联了部门信息(中间结果):

d1.emp_no (员工)d2.emp_no (经理)
1000110002

现在需要补充薪资:

  1. 第一次 JOIN salaries (d3):拿 10001 的薪资 → 88958

  2. 第二次 JOIN salaries (d4):拿 10002 的薪资 → 72527

如果只关联一次,要么只能拿到员工薪资,要么只能拿到经理薪资,无法同时获得两者进行比较。


类比理解

就像你要比较两个人的身高:

  • 需要查第一个人的身高记录

  • 也需要查第二个人的身高记录

  • 即使数据存在同一张「身高表」里,也要查两次,因为查询条件不同(一次查 A,一次查 B)


其他写法(了解即可)

理论上也可以把salaries分别起别名,写成子查询,但本质还是两次访问:

sql

SELECT d1.emp_no, d2.emp_no AS manager_no, (SELECT salary FROM salaries WHERE emp_no = d1.emp_no AND to_date = '9999-01-01') AS emp_salary, (SELECT salary FROM salaries WHERE emp_no = d2.emp_no AND to_date = '9999-01-01') AS manager_salary FROM dept_emp d1 JOIN dept_manager d2 ON d1.dept_no = d2.dept_no WHERE ...;

两次 JOIN 的方式更清晰、性能通常更好


总结

需要的数据来自哪条记录关联条件
员工薪资salaries 表,对应 emp_no = 员工编号d1.emp_no = d3.emp_no
经理薪资salaries 表,对应 emp_no = 经理编号d2.emp_no = d4.emp_no

每人一条薪资记录 → 需要两次独立的 JOIN


还是不理解为什么要关联两次薪资表,领导也在员工表中,第一次员工表关联薪资表,不就可以查出领导的薪资吗


你说得非常对!这个问题的核心就在这里,让我详细解释为什么不能一次查出


你的理解误区

你说"领导也在员工表中",这是正确的。但问题在于:

一次关联查询,只能为一"条"记录获取薪资


具体例子说明

假设我们已经关联了部门和经理关系(中间结果):

text

dept_emp (普通员工) dept_manager (经理) emp_no | dept_no dept_no | emp_no (经理) 10001 | d001 d001 | 10002

这时,一条查询结果记录包含:

  • 员工编号:10001

  • 经理编号:10002

现在要取薪资

如果你只关联一次 salaries 表

sql

JOIN salaries s ON ???.emp_no = s.emp_no

这个ON条件只能选一个:

  • 如果 ONde.emp_no = s.emp_no→ 能拿到员工薪资(10001的薪资),拿不到经理薪资

  • 如果 ONdm.emp_no = s.emp_no→ 能拿到经理薪资(10002的薪资),拿不到员工薪资

无法同时满足"一条记录里既有员工薪资,又有经理薪资"


为什么不能用子查询或窗口函数?

你可能觉得:既然领导在员工表里,那用子查询不行吗?

sql

SELECT de.emp_no, dm.emp_no AS manager_no, s1.salary AS emp_salary, (SELECT salary FROM salaries s2 WHERE s2.emp_no = dm.emp_no ...) AS manager_salary FROM ...

这样写本质还是两次访问 salaries 表,只不过第二次访问写成了子查询。


换个角度理解:关系型数据库的"行"概念

每张表关联一次,是在给当前结果集的每一行新增列。

初始结果集(未关联薪资前):

员工编号经理编号
1000110002
1000310004

要变成最终结果:

员工编号经理编号员工薪资经理薪资
10001100028895872527
1000310004??

你需要:

  1. 根据"员工编号"这一列去 salaries 表查薪资 → 得到"员工薪资"列

  2. 根据"经理编号"这一列去 salaries 表查薪资 → 得到"经理薪资"列

这必然需要两次独立的查找操作


类比理解

想象你有两张表:

  • 人员表:姓名、性别

  • 收入表:姓名、工资

现在要查:张三(员工)和他的领导李四(也在人员表中)的工资对比

一次查询结果需要包含:

员工姓名员工工资领导姓名领导工资
张三8000李四15000

你要去"收入表"查两次:

  1. 查"张三"的工资 → 8000

  2. 查"李四"的工资 → 15000

虽然张三和李四都在同一张人员表,但他们是不同的记录,必须分别查收入表。


什么时候可以关联一次?

只有当你要获取的薪资来自同一个人时:

sql

-- 查询员工及其自己的薪资(只需要关联一次) SELECT de.emp_no, s.salary FROM dept_emp de JOIN salaries s ON de.emp_no = s.emp_no

但你要比较的是员工 vs 领导(两个人),所以必须关联两次。


总结

你的想法实际情况
"领导也在员工表中"✅ 正确
"所以一次关联就能拿到领导薪资"❌ 错误

根本原因

  • 一次 JOIN 是根据当前结果集中的某一个人去查薪资

  • 你的结果集中,一行记录包含两个人(员工和领导)

  • 因此必须分别为这两个人各 JOIN 一次 salaries 表

这就是为什么需要两次关联薪资表!


你的结果集中,一行记录包含两个人(员工和领导)?是两个人还是两类人,如果有第三个人要查薪资,难道还需关联第三次薪资表吗


非常精准的问题!让我用具体例子说明:

先回答你的问题

"一行记录包含两个人"是指两个不同的个体,不是"两类人"。

如果一行记录需要显示3个人的薪资,确实需要关联第3次薪资表!


具体例子:一行为什么会有两个人?

看这条SQL产生的中间结果(关联部门关系后,还没关联薪资):

sql

SELECT de.emp_no, dm.emp_no AS manager_no FROM dept_emp de JOIN dept_manager dm ON de.dept_no = dm.dept_no

结果集(未关联薪资前):

员工编号经理编号
1000110002
1000310002(假设同一个部门有多个员工)
1000410005

每一行包含了两个人

  • 第1列:员工(一个人)

  • 第2列:经理(另一个人)

虽然经理也是员工,但在这一行记录里,他们是两个不同的具体的人


如果要查第三个人的薪资

假设需求变成:员工、经理、总监三者的薪资对比

表结构:

  • dept_emp:员工

  • dept_manager:经理

  • dept_director:总监

sql

WITH current_salary AS ( SELECT emp_no, salary FROM salaries WHERE to_date = '9999-01-01' ) SELECT de.emp_no, dm.emp_no AS manager_no, dd.emp_no AS director_no, s1.salary AS emp_salary, s2.salary AS manager_salary, s3.salary AS director_salary -- 第三个人的薪资 FROM dept_emp de JOIN dept_manager dm ON de.dept_no = dm.dept_no JOIN dept_director dd ON de.dept_no = dd.dept_no JOIN current_salary s1 ON de.emp_no = s1.emp_no -- 关联第1次:员工 JOIN current_salary s2 ON dm.emp_no = s2.emp_no -- 关联第2次:经理 JOIN current_salary s3 ON dd.emp_no = s3.emp_no; -- 关联第3次:总监

确实需要关联3次薪资表,因为一行结果集包含了3个不同的人


核心规律

结果集中,有几个"角色"需要显示薪资,就需要关联几次薪资表

需求结果集一行包含关联薪资表次数
员工自己1个人1次
员工 vs 经理2个人2次
员工 vs 经理 vs 总监3个人3次
员工 vs 他的5个上级6个人6次

为什么容易混淆?

你可能会想:"经理也是员工,为什么不能一次查出?"

因为SQL的JOIN是基于值匹配,不是基于"角色":

  • 第一次JOIN:用"员工编号"去匹配 → 拿到员工薪资

  • 第二次JOIN:用"经理编号"去匹配 → 拿到经理薪资

即使是同一张表,只要查询条件不同(不同的emp_no),就需要分别JOIN。


总结

你的理解正确理解
"一行记录包含两类人"❌ 是两个具体的人
"经理也在员工表,应该一次查出"❌ 不同的人需要不同的查询条件
"有第三个人就需要第三次关联"完全正确

这就是为什么你的原SQL需要两次关联salaries表——因为一行结果集里,员工和经理是两个不同的具体的人

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 19:49:31

手机号查QQ号:Python开源工具终极指南

手机号查QQ号:Python开源工具终极指南 【免费下载链接】phone2qq 项目地址: https://gitcode.com/gh_mirrors/ph/phone2qq 你是否遇到过需要快速查询手机号对应QQ号的情况?无论是验证用户身份、核对联系方式,还是进行数据关联分析&am…

作者头像 李华
网站建设 2026/4/30 19:47:30

S32K3系列MCU内存管理避坑指南:ITCM/DTCM、RAM、Flash到底怎么分?

S32K3系列MCU内存管理实战解析:从TCM原理到工程配置 第一次接触S32K3系列MCU的内存架构时,看着数据手册上密密麻麻的地址映射图和IDE中复杂的linker配置,相信不少开发者都会感到困惑——ITCM、DTCM、SRAM、Flash这些存储区域到底有什么区别&a…

作者头像 李华
网站建设 2026/4/30 19:43:23

lazygit.nvim开发者指南:如何扩展功能和贡献代码

lazygit.nvim开发者指南:如何扩展功能和贡献代码 【免费下载链接】lazygit.nvim Plugin for calling lazygit from within neovim. 项目地址: https://gitcode.com/gh_mirrors/la/lazygit.nvim lazygit.nvim是一款让开发者在Neovim中直接调用lazygit的插件&a…

作者头像 李华
网站建设 2026/4/30 19:41:25

终极CodeIgniter入门指南:20分钟掌握PHP框架实战技巧

终极CodeIgniter入门指南:20分钟掌握PHP框架实战技巧 【免费下载链接】CodeIgniter Open Source PHP Framework (originally from EllisLab) 项目地址: https://gitcode.com/gh_mirrors/co/CodeIgniter CodeIgniter是一款轻量级的开源PHP框架,以其…

作者头像 李华