再探再报:SQL中的关联查询

在 SQL 中进行关联查询(或称联接查询)时,有几种不同的语法来执行这些查询,常见的包括:

  1. 使用 JOIN 关键字JOIN 关键字可与不同类型的联接组合使用,如 INNER JOINLEFT JOINRIGHT JOINFULL JOIN 等。例如:

    SELECT *
    FROM TableA
    INNER JOIN TableB ON TableA.column = TableB.column;
    

    这种语法通过 ON 关键字指定连接条件进行表联接。

  2. 使用逗号分隔表:在 FROM 子句中可以列出多个表名,使用逗号分隔。但不推荐在实际应用中使用这种方式,因为它与 ANSI SQL 标准不太一致,并且可读性较差。示例:

    SELECT *
    FROM TableA, TableB
    WHERE TableA.column = TableB.column;
    

    此种方式实际上会执行笛卡尔积,然后通过 WHERE 子句进行过滤以得到想要的结果。不过,应该尽量避免使用这种语法,而是采用显式的 JOIN 语法。

  3. 子查询:在 SELECT 语句中嵌套使用子查询来执行关联查询。例如:

    SELECT *
    FROM TableA
    WHERE TableA.column IN (SELECT column FROM TableB WHERE condition);
    

    这种方式将一个查询的结果嵌套到另一个查询中,用于创建关联。这种方法适用于特定情况下的复杂查询。

以上是 SQL 中进行关联查询常用的几种语法形式。在实际应用中,推荐使用 JOIN 语法,因为它更为清晰明了,易于理解,并且符合 ANSI SQL 标准。

1.Join语法

1.1. LEFT JOIN

在数据库中,LEFT JOIN 是一种用于联结多个表的 SQL 查询语句。LEFT JOIN 返回左边表(也称为主表)中的所有记录,并且如果在右边表(也称为外部表)中存在匹配的记录,则返回匹配的记录。如果右边表中没有匹配的记录,则返回 NULL 值。

语法如下所示:

SELECT 列名列表
FROM 左边表
LEFT JOIN 右边表 ON 左边表.列名 = 右边表.列名;

这里有一个示例来说明 LEFT JOIN 的工作原理。假设有两个表 StudentsGrades

Students 表:

IDName
1Alice
2Bob
3Charlie

Grades 表:

Student_IDGrade
1A
2B
4C

如果使用 LEFT JOIN 来结合这两个表,查询学生和他们的成绩(如果有的话),语句如下:

SELECT Students.Name, Grades.Grade
FROM Students
LEFT JOIN Grades ON Students.ID = Grades.Student_ID;

执行这个查询后,会得到如下结果:

NameGrade
AliceA
BobB
CharlieNULL

这个结果解释如下:

  • Alice 和 Bob 在 Students 表和 Grades 表中都有匹配的记录,因此他们的成绩被显示出来。
  • Charlie 在 Students 表中有记录,但在 Grades 表中没有匹配的记录,因此他的成绩显示为 NULL

总之,LEFT JOIN 允许您检索左边表中的所有记录,并根据右边表中的匹配条件,返回相应的数据。如果右边表中没有匹配的记录,则返回 NULL

1.2. LEFT JOIN和INNER JOIN

INNER JOINLEFT JOIN 是 SQL 中常用的两种连接(或联结)表的方法,它们之间有一些重要的区别:

  1. INNER JOIN

    • INNER JOIN 返回两个表中满足连接条件的匹配行。
    • 结果集中只包含在两个表中都存在匹配的行。
    • 如果在左表或右表中没有匹配的行,则这些行不会出现在结果中。
    • 语法示例:
      SELECT * FROM TableA INNER JOIN TableB ON TableA.column = TableB.column;
      
  2. LEFT JOIN

    • LEFT JOIN 返回左表中的所有行,以及右表中与左表中行匹配的行(如果有匹配的话)。
    • 如果右表中没有匹配的行,则在结果集中相关列显示为 NULL
    • 左表中的所有行都会出现在结果中,无论右表中是否有匹配。
    • 语法示例:
      SELECT * FROM TableA LEFT JOIN TableB ON TableA.column = TableB.column;
      

举例说明:

假设有两个表:EmployeesDepartments

Employees

| EmployeeID | EmployeeName | DepartmentID |
|------------|--------------|--------------|
| 1          | Alice        | 1            |
| 2          | Bob          | 2            |
| 3          | Charlie      | 1            |

Departments 表:

| DepartmentID | DepartmentName |
|--------------|----------------|
| 1            | Sales          |
| 2            | Marketing      |
| 3            | HR             |

现在来比较 INNER JOINLEFT JOIN 的区别:

INNER JOIN 示例:

SELECT Employees.EmployeeName, Departments.DepartmentName
FROM Employees
INNER JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

结果将是只有 Sales 和 Marketing 部门的员工信息:

| EmployeeName | DepartmentName |
|--------------|----------------|
| Alice        | Sales          |
| Bob          | Marketing      |
| Charlie      | Sales          |

注意,只有 Sales 和 Marketing 部门的员工被返回,因为只有这两个部门在 Employees 表和 Departments 表中都有匹配的记录。

LEFT JOIN 示例:

SELECT Employees.EmployeeName, Departments.DepartmentName
FROM Employees
LEFT JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

结果将包括所有员工信息,但是对于 HR 部门(在 Departments 表中存在但在 Employees 表中没有匹配的记录),相关的部门信息显示为 NULL

| EmployeeName | DepartmentName |
|--------------|----------------|
| Alice        | Sales          |
| Bob          | Marketing      |
| Charlie      | Sales          |
| NULL         | HR             |

在这个例子中,LEFT JOIN 返回了 Employees 表中的所有员工信息,包括 HR 部门,因为它是左连接。但是,由于在 Employees 表中没有与 HR 部门相关的记录,所以在 DepartmentName 列中显示为 NULL

1.3. FULL JOIN

FULL JOIN 是 SQL 中用于连接两个表并返回它们之间所有匹配和不匹配行的联接操作。FULL JOIN 结合了 LEFT JOINRIGHT JOIN 的功能,它返回两个表中的所有行,并且对于不匹配的行,其中一个表中无对应匹配的行,相关列会显示 NULL 值。

语法结构如下:

SELECT *
FROM TableA
FULL JOIN TableB ON TableA.column = TableB.column;
  • FULL JOIN 结果包括了 LEFT JOINRIGHT JOIN 的结果,以及两个表中不匹配的行。
  • 返回的结果集包括了左表中所有的行和右表中所有的行,以及根据连接条件匹配的行。
  • 如果在连接条件中找不到匹配的行,则相关列将显示为 NULL
  • 如果一个表中有匹配而另一个表中没有匹配的行,结果集中将分别显示两个表中的数据,但没有对应的匹配值。

举个例子说明:

假设有两个表 EmployeesDepartments

Employees 表:

EmployeeIDEmployeeNameDepartmentID
1Alice1
2Bob2
3Charlie3

Departments 表:

DepartmentIDDepartmentName
1Sales
2Marketing
4HR

使用 FULL JOIN 进行联接:

SELECT Employees.EmployeeID, Employees.EmployeeName, Departments.DepartmentName
FROM Employees
FULL JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

结果可能如下:

EmployeeIDEmployeeNameDepartmentName
1AliceSales
2BobMarketing
3CharlieNULL
NULLNULLHR

以上结果显示了两个表中的所有行。前两行分别表示有匹配的员工和他们的部门,第三行表示一个员工在 Employees 表中有记录但在 Departments 表中没有匹配的部门信息,第四行表示在 Departments 表中有记录但在 Employees 表中没有匹配的员工信息。

1.4. CROSS JOIN

CROSS JOIN 是 SQL 中用于执行笛卡尔积(Cartesian Product)的一种联接方式。它返回两个表中所有可能的组合,即左表中的每一行都与右表中的每一行进行组合,生成一个新的虚拟表。

CROSS JOIN 不需要任何连接条件,因此它不关心两个表之间是否有相关的列或条件。它简单地将一个表的每一行与另一个表的每一行进行匹配,生成的结果行数为两个表行数的乘积。

语法如下:

SELECT *
FROM TableA
CROSS JOIN TableB;

举例说明:

假设有两个表 StudentsCourses

Students 表:

StudentIDStudentName
1Alice
2Bob

Courses 表:

CourseIDCourseName
101Math
102Science

使用 CROSS JOIN 进行联接:

SELECT Students.StudentID, Students.StudentName, Courses.CourseID, Courses.CourseName
FROM Students
CROSS JOIN Courses;

结果将是两个表中所有行的组合:

StudentIDStudentNameCourseIDCourseName
1Alice101Math
1Alice102Science
2Bob101Math
2Bob102Science

在这个例子中,CROSS JOIN 返回了所有可能的学生和课程的组合,因为它不需要任何连接条件,所以它生成了两个表中所有行的笛卡尔积。需要注意的是,笛卡尔积会导致结果集行数快速增加,因此在实际应用中,应慎重使用 CROSS JOIN,特别是当两个表的行数较大时,可能会生成巨大的结果集。

2.逗号分隔表

逗号分隔表(Comma-Separated Tables)是 SQL 中一种在 FROM 子句中列出多个表的语法形式,用逗号 , 将表名分隔开来,从而允许同时查询多个表。这种语法可以用于执行表联接操作,但是它的使用方式不够明确,可读性较差,因此不推荐在实际开发中广泛使用。

2.1. 案例一

在逗号分隔表的语法中,可以列出多个表,并在查询中引用这些表。例如:

SELECT *
FROM TableA, TableB;

这样的语法形式将返回两个表的笛卡尔积。如果没有指定连接条件或者其他约束,将会生成两个表的所有可能的组合,称为笛卡尔积。

通常情况下,在逗号分隔表的写法下,如果没有指定 WHERE 子句或者其他连接条件,可能会意外地生成笛卡尔积,结果是两个表的所有行的组合。这可能会导致意外的大量数据,特别是当表中的行数很大时,这种查询会产生非常庞大的结果集。

2.2. 案例二

SELECT *
FROM TableA
INNER JOIN TableB ON TableA.id = TableB.id;

这个查询使用了逗号分隔表名的方式,并在 WHERE 子句中指定了连接条件 TableA.id = TableB.id。虽然这种写法可以执行表的联接操作,但实际上这是一个隐式的内连接。

这条查询语句会返回 TableATableB 中满足连接条件的行。在这种情况下,由于在 WHERE 子句中指定了 TableA.id = TableB.id,它执行了一个内连接,只返回两个表中在 id 列上匹配的行。

这种写法虽然能够实现表的联接,但不够明确。推荐使用显式的 JOIN 语法(如 INNER JOIN)来进行联接操作,因为它更清晰、易读,并且可以更明确地表达查询的意图,例如:

SELECT *
FROM TableA
INNER JOIN TableB ON TableA.id = TableB.id;

这种写法使用了明确的 INNER JOIN 语法来执行相同的内连接操作,更容易理解和维护。

2.3. 注意

  • 使用逗号分隔表进行表联接操作是一种较老的 SQL 写法,在现代的 SQL 标准中,更推荐使用显式的 JOIN 语法(如 INNER JOINLEFT JOIN 等),因为它们更为清晰和易读,并且能够明确表达查询的意图。
  • 显式使用 JOIN 语法(例如 INNER JOIN)能够提高代码的可读性,同时也更容易理解和维护。

3.子查询

子查询是指在 SQL 查询中嵌套的另一个查询。它允许在一个 SQL 查询中使用另一个查询的结果集作为条件或数据源。子查询可以嵌套在 SELECTINSERTUPDATEDELETE 语句的各个部分中,用于执行特定的子任务或过滤条件。

子查询通常用于以下场景:

  1. WHERE 子句中的子查询:作为过滤条件使用。
SELECT column1, column2
FROM table1
WHERE column1 = (SELECT column1 FROM table2 WHERE condition);
  1. FROM 子句中的子查询:作为数据源使用。
SELECT column1, column2
FROM (SELECT column1, column2 FROM table1) AS subquery;
  1. 在 INSERT 语句中的子查询:用于从另一个表中选择数据插入到目标表中。
INSERT INTO table1 (column1, column2)
SELECT column1, column2
FROM table2
WHERE condition;
  1. 在 UPDATE 语句中的子查询:用于根据另一个查询的结果更新数据。
UPDATE table1
SET column1 = (SELECT column1 FROM table2 WHERE condition)
WHERE condition;

子查询可以是标量子查询(返回单个值)、行子查询(返回一行结果集)或表子查询(返回多行结果集)。它们提供了更灵活的方式来构建复杂的查询,可以根据需要嵌套多个层级的子查询。

尽管子查询功能强大,但过多或复杂的嵌套子查询可能会降低查询性能。因此,在使用子查询时,需要谨慎选择合适的条件和结构,并进行必要的优化以确保查询的效率和性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/221998.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DPDK多进程之间的通信

文章目录 前言本机DPDK IPC API介绍demo演示 前言 DPDK的主进程和辅助进程之间共享大页内存。关于DPDK多进程的支持文档介绍见:47. 多进程支持。 本文介绍本机DPDK的主进程和辅助进程之间交换短消息的API的使用。 前置要求:DPDK-Hello-World示例应用程…

系统级基础信号知识【Linux】

目录 一,什么是信号 进程面对信号常见的三种反应概述 二,产生信号 1.终端按键产生信号 signal 2. 进程异常产生信号 核心转储 3. 系统调用函数发送信号 kill raise abort 小结: 4. 由软件条件产生 alarm 5. 硬件异常产生信号…

解锁MSSQL存储过程优化之道:参数化查询的技术深度探究

数据库是现代应用的支柱,而MSSQL作为其中的瑞士军刀,其性能直接关系到系统的稳定与响应速度。本文将带领读者深入探讨MSSQL存储过程优化的精髓之一——参数化查询。跟随着我们的脚步,你将领悟到优化的本质,发现隐藏在参数化查询背…

WEB服务器介绍

Web服务器是指驻留于因特网上某种类型计算机的程序。当Web浏览器连到服务器上并请求文件时,服务器将处理该请求并将文件发送到该浏览器上,附带的信息会告诉浏览器如何查看该文件,即文WEB服务器件类型。服务器使用HTTP进行信息交流&#xff0c…

Java之异常

一、异常是什么 程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。 注意:异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行. 二、异常体系 三、异常的分类 (一)、编译时…

明懿金汇应对气候变化:投资于绿色未来

2023年,面对全球范围内的气候变化和环境保护挑战,明懿金汇积极响应,展现出其在可持续金融领域的领导力。作为一家前沿的金融科技公司,明懿金汇不仅将环保理念融入到其金融产品和服务中,更通过直接的行动和投资&#xf…

【Python】conda镜像配置,.condarc文件详解,channel镜像

1. conda 环境 安装miniconda即可,Miniconda 安装包可以到 http://mirrors.aliyun.com/anaconda/miniconda/ 下载。 .condarc是conda 应用程序的配置文件,在用户家目录(windows:C:\users\username\),用于…

PHP的协程是什么?

PHP 的协程是一种轻量级的线程(或任务)实现,允许在一个进程中同时执行多个协程,但在任意时刻只有一个协程处于执行状态。协程可以看作是一种用户空间线程,由程序员显式地管理,而不是由操作系统内核进行调度…

用提问的方式来学习:冯·诺伊曼体系结构与操作系统OS

学习冯诺伊曼体系结构之前,我们要本着两个问题来学习: 什么是冯诺伊曼体系结构?为什么要有冯诺伊曼体系结构? 一、冯诺伊曼体系结构 1. 什么是冯诺伊曼体系结构? 那我们就先来回答一下什么是冯诺伊曼体系结构&#x…

Python中的TesserOCR:文字识别的全方位指南

更多资料获取 📚 个人网站:ipengtao.com 文字识别在图像处理领域中起到了至关重要的作用,而TesserOCR(Tesseract OCR的Python封装)为开发者提供了一个强大的工具,使得文字识别变得更加便捷。本文将通过详细…

Matlab示例-Examine 16-QAM Using MATLAB学习笔记

​工作之余学习16-QAM 写在前面 网上看到许多示例,但一般都比较难以跑通。所以,还是老方法,先将matlab自带的例子研究下。 Examine 16-QAM Using MATLAB Examine 16-QAM Using MATLAB 或者,在matlab中,键入&#x…

Spring框架-GOF代理模式之JDK动态代理

我们可以分成三步来完成jdk动态代理的实现 第一步:创建目标对象 第二步:创建代理对象 第三步:调用代理对象的代理方法 public class Client {public static void main(String[] args) {//创建目标对象final OrderService target new OrderS…

C语言数据结构-二叉树的入门

文章目录 0 碎碎念1 二叉树的概念和结构1.1 概念和特点1.2 结构1.3 特殊的二叉树1.4 二叉树的存储与性质1.5 前序、中序和后序 2 简单二叉树的实现2.1 定义数据结构类型2.2 前序、中序和后序接口的实现2.3 二叉树中节点的个数2.4 叶子节点的个数 3 完整代码块3.1 BinaryTree.h3…

「神印王座」皓晨带伙伴参与伊老试炼,12魔神攻打震南关,高能

Hello,小伙伴们,我是拾荒君。 时光匆匆,国漫《神印王座》的第85集已经与大家如约而至。想必各位观众都已经迫不及待地观看了这一集,其中,龙皓晨向光之晨曦团的成员们揭示了永恒之塔的秘密,并带领他们深入其中。 永恒之…

Java实现pdf文件合并

在maven项目中引入以下依赖包 <dependencies><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox-examples</artifactId><version>3.0.1</version></dependency><dependency><groupId>co…

全志V3s之显示当前文件路径

新移植的kernel和根文件系统&#xff0c;其终端显示只有一个#号&#xff0c;不方便查看&#xff0c;更改以下配置&#xff0c;使得可以显示全路径。修改如下&#xff1a; export PS1[\u\h \w]\$这个是即时生效的&#xff0c;所以如果要重启或者重新打开窗口也生效的话就要把这…

nginx服务前端访问查看无响应的问题

问题 nginx 启动之后&#xff0c;前端访问无数据&#xff0c;F12 查看&#xff0c;提示挂起。 以为是配置问题&#xff0c;查看配置文件&#xff0c;未发现配置的有问题。 原因 通过查看配置文件&#xff0c;发现转发的服务地址为127.0.0.1&#xff0c;手动ping 127.0.0.1&a…

如何部署Portainer容器管理工具+cpolar内网穿透实现公网访问管理界面

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 本文主要介绍如何本地安装Portainer并结合内网穿透工具实现任意浏览器远程访问管理界面。Portainer 是一个轻量级…

Unity 关于Rigidbody刚体组件的理解

一、基本了解 刚体Rigidbody因具体物理相关的属性&#xff0c;使得实际应用中更有真实感。应用也多&#xff1a; Rigidbody它可以受到重力、碰撞或者力的作用&#xff0c;所以我们可以用它模拟物体的真实物理行为&#xff0c;如受到重力的作用、与其他刚体对象进行碰撞&#…

QT之QTransform

QT之QTransform 成员函数例程 成员函数 QTransform函数&#xff1a; translate(x,y)&#xff1a;平移。 rotate(a)&#xff1a;旋转&#xff08;a为角度值&#xff09;。 scale(sx,sy)&#xff1a;缩放。 shear(shx,shy)&#xff1a;斜切。 setMatrix(m11,m12,m21,m22,dx,dy)&…