【SQL221】题解 | 统计各个部门的工资记录数
统计各个部门的工资记录数
https://www.nowcoder.com/practice/6a62b6c0a7324350a6d9959fa7c21db3
这道题是统计各个部门的工资记录数,给出部门编码dept_no、部门名称dept_name以及部门在salaries表里面有多少条记录sum,按照dept_no升序排序。
# 思路:
# 1.将dept_emp表和薪水表salaries表按照员工编号相等的标准连接,按照员工编号相等的标准用group by函数统计出每个员工的工资记录数emp_salary_num
# 2.将统计出来的表按照部门编号相等的标准和departments表连接,按照部门编号相等的标准用group by函数统计出每个部门的工资记录数dep_salary_num
# select d.dept_no, d.dept_name, b.sum from departments d join (select d.dept_no, count(*) as sum from departments d join (select de.emp_no, count(*) as emp_salary_num from dept_emp de join salaries s on de.emp_no = s.emp_no group by de.emp_no) e on d.dept_no = de.dept_no group by d.dept_no) b;
# select
# d.dept_no,
# d.dept_name,
# b.sum
# from
# departments d
# join
# (select
# de.dept_no,
# count(*) as sum
# from
# dept_emp de
# join
# salaries s
# on de.emp_no = s.emp_no
# group by de.dept_no) b
# on d.dept_no = b.dept_no;
# 上述是采用子查询的方法
select
d.dept_no,
ds.dept_name,
count(*) as sum
from
salaries s
join dept_emp d on s.emp_no = d.emp_no
join departments ds on ds.dept_no = d.dept_no
group by
d.dept_no,
ds.dept_name
order by
d.dept_no asc;
# 直接用join将三个表连接起来,然后用group by d.dept_no, ds.dept_name分组聚合统计
【思考:为什么子查询中要将临时表取个别名,但是上述的查询不需要将join之后的临时表取个别名呢】
在 SQL 中,子查询和**JOIN** 的处理方式有所不同,导致在子查询中需要给临时表起别名,而在 JOIN 查询中不需要对连接后的结果集命名。
1. 子查询中的临时表必须给别名
在 SQL 中,子查询(尤其是在 FROM 子句中)会生成一个临时结果集,这个结果集是匿名的。为了在外部查询中引用它,必须为子查询结果集提供一个别名。
为什么子查询需要别名?
- 子查询的结果:在子查询中执行某些计算或筛选时,SQL 会生成一个临时的结果集。如果这个临时结果集没有别名,SQL 引擎就不知道如何引用它。
- 别名的作用:别名使得外部查询可以引用子查询的结果,尤其是当子查询生成多个列时,我们需要通过别名来引用它们。
例如:
SELECT *
FROM (
SELECT emp_no, dept_no
FROM dept_emp
WHERE emp_no = 1001
) AS subquery_alias;
在这个查询中,AS subquery_alias 是给子查询结果起的别名。这个别名是必需的,否则 SQL 引擎会报错,因为外部查询需要引用这个临时结果集。
2. JOIN 查询中的临时表不需要显式的别名
当你进行 JOIN 操作时,SQL 会自动生成一个结果集,这个结果集不需要显式给定别名,因为你是在 FROM 子句中直接引用原始表或表的别名。
为什么 JOIN 不需要显式的别名?
- JOIN 的结果是即时生成的:在执行 JOIN 操作时,SQL 自动把多个表的数据按条件组合到一起,并生成一个 "临时结果集"。这个结果集是动态的,它会在查询执行时直接被用来提供数据。
- 表的别名:你可以通过在 JOIN 中给表取别名(如 FROM dept_emp d)来引用表,而不需要对整个连接结果集再取一个新的别名。JOIN 操作通常通过 ON 子句指定连接条件,然后通过 SELECT 语句直接选择连接后的结果集中的列。
示例:
SELECT
d.dept_no,
ds.dept_name,
COUNT(*) AS sum
FROM
salaries s
JOIN
dept_emp d ON s.emp_no = d.emp_no
JOIN
departments ds ON ds.dept_no = d.dept_no
GROUP BY
d.dept_no, ds.dept_name
ORDER BY
d.dept_no ASC;
在这个查询中,JOIN 连接了三个表,分别是 salaries、dept_emp 和 departments。你不需要给连接的结果集起别名,因为每个表的列可以通过表的别名(如 s, d, ds)来引用。
3. 子查询与 JOIN 的区别
- 子查询:通常用于 生成一个独立的结果集,然后这个结果集被用于外部查询中。由于这个结果集没有名字,必须给它取一个别名。
- JOIN:通常是将两个或多个表 合并为一个单一的结果集。这些表的列可以通过表的别名来引用,而不需要额外的别名。
4. 总结:
- 子查询需要别名:因为子查询的结果集本身是一个临时生成的表,你必须给它一个别名才能在外部查询中引用。
- JOIN 查询不需要额外的别名:因为 JOIN 只是对两个表的行进行合并,原始表的别名(如 s, d, ds)已经能清楚地标识每个表的列,所以不需要额外的别名。
希望这个解释清晰地阐明了为什么子查询需要别名,而 JOIN 查询中不需要显式给连接后的结果集命名!
SQL学习专栏 文章被收录于专栏
发个sql学习和实践的小记录

