mysql - 无法理解涉及跨不同表的不同列的 SQL 查询中的控制流
问题描述
我想改进我的 SQL,为此我需要了解 SQL 中的控制流。我了解基础知识,但这是一个这样的例子,我无法理解如何在不同查询(子查询)中的另一个表的 where 子句中使用一个表中的列?
这是问题陈述。查询是:
SELECT
IF (Grade >= 8, Name, NULL),
Grade,
Marks
FROM
(SELECT
Name,
(SELECT Grade FROM Grades WHERE (Min_Mark <= Marks) AND (Marks <= Max_Mark)) AS Grade,
Marks
FROM Students) As MyStudents
ORDER BY Grade DESC, Name;
我的疑问是在子查询中:(SELECT Grade FROM Grades WHERE (Min_Mark <= Marks) AND (Marks <= Max_Mark))
,为什么可以使用“标记”?
解决方案
您所拥有的是所谓的相关子查询,MySQL(和许多其他 RDBMS)允许来自外部查询的字段在子查询中引用一个“层”深。一种查看方式是子查询可以访问它们所包含的查询范围,但不能访问更远的范围。
在多表查询中,最好用它们来自的表(或表的别名)来限定所有字段名称,以使查询更易于阅读;这在这种情况下尤其重要,因为在您的查询的当前形式中,它甚至具有相关性并不明显。
在来自外部查询的小数据集上,特别是当子查询中的数据计算成本相对较高时,相关子查询可以更快;但是当来自外部查询的大量数据必须由相关子查询处理时,相关子查询可能会变得非常昂贵,因为相关子查询被重复处理(外部查询中的每一行一次)。
此外,必须注意外部查询的 SELECT 中的子查询。这样的子查询必须只返回一行。
作为一般规则,除非子查询大大减少连接的行数,否则连接几乎总是性能更好。
您的查询似乎不需要任何子查询:
SELECT IF(g.Grade >= 8, s.Name, NULL)
, g.Grade
, s.Marks
FROM Students AS s
LEFT JOIN Grades AS g ON s.Marks BETWEEN g.Min_Mark AND g.Max_Mark
ORDER BY g.Grade DESC, s.Name
;
推荐阅读
- c# - 在 C# (Unity) 中关闭文件
- excel - 在 Excel 中求和返回 0
- c - 在运行 Ubuntu 19.10 的 x64 系统中,文件描述符的比特大小是多少?
- javascript - 如何在 Laravel 中为当前用户提交信息?
- go - Gorilla mux - 在将请求传递给路由器之前修改请求
- sql - Update statement where condtion is neglected
- authentication - 颤振http异常
- html - 如何计算` `元素的高度
- mongodb - 如何在 MongoDB 中将待办事项或更多内容保存在创建它们的用户的数组属性中?
- oracle - Oracle如何更新一张表中的多列