【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 连接了三个表,分别是 salariesdept_empdepartments。你不需要给连接的结果集起别名,因为每个表的列可以通过表的别名(如 s, d, ds)来引用。

3. 子查询与 JOIN 的区别

  • 子查询:通常用于 生成一个独立的结果集,然后这个结果集被用于外部查询中。由于这个结果集没有名字,必须给它取一个别名。
  • JOIN:通常是将两个或多个表 合并为一个单一的结果集。这些表的列可以通过表的别名来引用,而不需要额外的别名。

4. 总结:

  • 子查询需要别名:因为子查询的结果集本身是一个临时生成的表,你必须给它一个别名才能在外部查询中引用。
  • JOIN 查询不需要额外的别名:因为 JOIN 只是对两个表的行进行合并,原始表的别名(如 s, d, ds)已经能清楚地标识每个表的列,所以不需要额外的别名。

希望这个解释清晰地阐明了为什么子查询需要别名,而 JOIN 查询中不需要显式给连接后的结果集命名!

SQL学习专栏 文章被收录于专栏

发个sql学习和实践的小记录

全部评论

相关推荐

03-05 17:03
已编辑
浙江工商大学 C++
陈好好wy:整体看下来有点空空的感觉,可以把每一段项目经历都再完善一下,然后用小标题的形式写个两到三条,目前看有点太简单了,不太能看出具体在这个项目里做了什么工作。还是要尽量把自己做的工作以量化的形式体现在简历上呢。
双非本科求职如何逆袭
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务