当前位置: 首页> 科技> 互联网 > 网站 seo_广州做网站哪个好_百度站长工具平台_创建自己的网站

网站 seo_广州做网站哪个好_百度站长工具平台_创建自己的网站

时间:2025/7/12 6:04:04来源:https://blog.csdn.net/galaxy223/article/details/146988168 浏览次数:0次
网站 seo_广州做网站哪个好_百度站长工具平台_创建自己的网站

深入解析SQL多表查询:核心技巧与实战示例

本文系统梳理SQL多表查询的核心方法,涵盖广义笛卡尔积、内连接(等值/自然连接)、外连接、子查询(相关/不相关)及集合运算。通过代码示例解析连接查询的陷阱与优化策略,探讨如何用子查询简化复杂逻辑,并实战“选修所有课程的学生查询”实现。适合希望提升SQL编写效率、深入理解多表交互逻辑的开发者,提供从基础到进阶的清晰学习路径。

文章目录

  • 深入解析SQL多表查询:核心技巧与实战示例
    • 广义笛卡尔积(交叉连接)
    • 内连接( θ \theta θ连接)
    • 等值连接
    • 自然连接
    • 给数据表起别名
    • 自身连接
    • 外连接
    • 子查询
      • 不相关子查询
      • 相关子查询
    • 查询结果的集合运算

广义笛卡尔积(交叉连接)

交叉连接会产生大量无效的行,实际中一般不常用,执行语句如下:

SELECT * 
FROMstudent,course ;

内连接( θ \theta θ连接)

通过一定的连接条件来连接两个表,常见的连接条件是比较运算,比如<或者>等等,如果比较运算符是=,就是等值连接。

等值连接

等值连接有两种方式:

SELECT * 
FROMstudent,score 
WHERE student.`sno` = score.`sno` ;
SELECT * 
FROMstudent INNER JOIN score ON student.`sno` = score.`sno` ;

建议使用第二种。

这样,就将学生表和成绩表合并到了一起,但是新表会有两列sno,如果只希望一列,使用自然连接:

自然连接

自然连接也有两种方式:

SELECT * 
FROMstudent JOIN score USING (sno) ;
SELECT * 
FROMstudent NATURAL JOIN score ;

这会自动合并相同列。

给数据表起别名

SELECT stu.sno,sname,c.`cno`,`grade` 
FROMstudent stu JOIN score sc ON stu.`sno` = sc.`sno` JOIN course c ON sc.`cno` = c.`cno` ;

只需要在FROM中的数据表后面加上别名即可。

[!note]

小练习:

查询所有选修了“数据结构”课程的学生学号、姓名和成绩:

SELECT stu.sno,sname,`grade` 
FROMstudent stu JOIN score sc ON stu.`sno` = sc.`sno` JOIN course c ON sc.`cno` = c.`cno` 
WHERE cname = '数据结构' ;

自身连接

别名的一个重要用途就是自身连接,通过对同一个数据表起不同的别名,可以将不同的别名看作不同的副本,例如想找年龄大于“吴强”的学生:

SELECT b.sname 
FROMstudent a,student b 
WHERE a.`sname` = '吴强' AND a.`birthday` > b.`birthday` ;

外连接

只需要在JOIN前面加上LEFT [OUTER]RIGHT [OUTER]FULL [OUTER]分别表示左外连接、右外连接、完全外连接。

子查询

不相关子查询

子查询可以很好地简化逻辑,允许一个查询结果作为返回值作为判定条件。例如,判断查询所有选修“数据结构”的学生姓名:

SELECT sno 
FROMscore 
WHERE cno = (SELECT cno FROMcourse WHERE cname = '数据结构') ;

比起等值连接,这样的逻辑更容易让人理解。再比如自身连接:

SELECT sname 
FROMstudent 
WHERE birthday < (SELECT birthday FROMstudent WHERE sname = '吴强') ;

上述的两个例子都是返回单值,子查询返回结果也可以作为集合:

SELECT sname 
FROMstudent 
WHERE sno IN (SELECT sno FROMscore WHERE cno = (SELECT cno FROMcourse WHERE cname = '数据结构')) ;

在子查询返回多值时,可以根据需要添加谓词:

SELECT * 
FROMstudent 
WHERE birthday < ALL (SELECT birthday FROMstudent WHERE dept = '软件工程') ;

上述语句ALL表示生日小于所有查询结果(等价于小于最小值),再比如:

SELECT * 
FROMstudent 
WHERE birthday < ANY (SELECT birthday FROMstudent WHERE dept = '软件工程') ;

上述ANY表示生日小于其中一个查询结果(等价于小于最大值)。上述两个例子也可以分别写成:

SELECT * 
FROMstudent 
WHERE birthday < (SELECT MIN(birthday) FROMstudent WHERE dept = '软件工程') ;
SELECT * 
FROMstudent 
WHERE birthday < (SELECT MAX(birthday) FROMstudent WHERE dept = '软件工程') ;

上述例子中,我们都是将子查询语句放在了WHERE语句中,但它也可以放在SELECTFROM中:

SELECT sno,totalcredit,(SELECT MAX(totalcredit) FROMstudent) AS '最高学分' 
FROMstudent ;

这样返回结果的每一行末尾都是相同的最高学分了

SELECT * 
FROM(SELECT * FROMstudent WHERE dept = '软件工程') AS app 
ORDER BY totalcredit DESC ;

注意,如果是将子查询结果作为表必须要为其设置别名。

[!note]

也可以用子查询结果创建、更新、插入、删除表,道理很简单,不再赘述。

相关子查询

相关子查询常用来实现关系代数中的除运算,比如要查找选修了所有课程的学生学号。

不相关子查询的子查询是独立的,也就是说子查询并不依赖于父查询,而相关子查询的部分信息依赖于父查询:

SELECT sno 
FROMstudent 
WHERE NOT EXISTS (SELECT cno FROMcourse WHERE NOT EXISTS (SELECT * FROMscore WHERE (sno = student.`sno` AND cno = course.`cno`))) ;

上述代码中,最内层子查询的==student.sno==依赖于最外层查询,==course.cno==依赖于中间层查询,执行过程中,会先利用父查询的一行执行子查询,子查询执行结束后利用父查询下一行数据进行子查询。

NOT EXISTS指的是:如果查询为空,返回True,有结果返回False。

最内层查询比较score表中的学号和课程号是否能在学生表和课程表中找到对应内容,如果找不到说明该课程和该学生没有关系,也就是没有选修的意思,

中间查询表示:如果内层查询有结果(NOT EXISTS返回False),那么查询结果就是空,如果内层查询无内容,那么结果就是这个课程号,反复执行子查询后就能找到一个学生没有选修的所有课程号。如果没有未选修课程那么返回就是空。

最外层就是检查是否为空,如果为空说明选修了所有课程,查询到结果。最后可以查询到选修了所有课程的学生。

查询结果的集合运算

SQL中对查询结果的运算仅支持并运算:

SELECT * 
FROMstudent 
WHERE birthday < ALL ((SELECT birthday FROMstudent WHERE dept = '软件工程') UNION((SELECT birthday FROMstudent WHERE dept = '计算机科学'))) ;

这样会默认去掉重复元组,如果想要保留只需要在UNION后面加上[ALL]即可。
``sql
SELECT
*
FROM
student
WHERE birthday < ALL (
(SELECT
birthday
FROM
student
WHERE dept = ‘软件工程’)
UNION
(
(SELECT
birthday
FROM
student
WHERE dept = ‘计算机科学’)
)
) ;


这样会默认去掉重复元组,如果想要保留只需要在`UNION`后面加上`[ALL]`即可。
关键字:网站 seo_广州做网站哪个好_百度站长工具平台_创建自己的网站

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: