SQL关联查询详解,SQL JOIN详解

article/2025/10/16 0:23:22

关联查询,也称为多表查询,指两个或更多个表一起完成查询操作。 前提条件:这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个关联字段可能建立了外键,也可能没有建立外键。

一、错误案例引入问题

1.案例说明

先来看几个简单的表,如下:

emp表:职工表,关联dept表

dept表:部门表,关联location表

location表:部门地区表

此时我们需要查询到员工的姓名及其部门名称:

如果我们错误的使用到下面的语句的话:

SELECT *
from emp,dept

得到结果如下:一共20条数据,它是对应emp的4条记录×dept的5条记录 

 我们把上述多表查询中出现的问题称为:笛卡尔积的错误。

2.笛卡尔积(或交叉连接)的理解

笛卡尔乘积是一个数学运算。假设我有两个集合 X 和 Y,那么 X 和 Y 的笛卡尔积就是 X 和 Y 的所有可能的组合,也就是第一个对象来自于 X,第二个对象来自于 Y 的所有可能。组合的个数即为两个集合中元素个数的乘积数。

SQL92中,笛卡尔积也称为交叉连接 ,英文是 CROSS JOIN 。在 SQL99 中也是使用 CROSS JOIN表示交叉连接。它的作用就是可以把任意表进行连接,即使这两张表不相关

在MySQL中如下情况会出现笛卡尔积:

select * from emp,dept
select * from emp cross join dept
select * from emp inner join dept
select * from emp join dept

inner join为内连接,等于join(省略了inner),内连接后面可以不接on

在上面的例子中笛卡尔积的不适应主要在于:emp表和dept表没有指明关联关系,导致表中的所有行互相连接

为了避免笛卡尔积错误,可以在where加上有效的连接条件,如下:

select *
from emp,dept
where emp.dept_id = dept.id

结果如下:

可以和前面的笛卡尔积错误的结果进行比较,该sql语句表示从笛卡尔积的结果中筛选出想要的数据(员工的部门id等于部门id)。

因为如此,陈七的部门id为null,在笛卡尔积中找不出陈七的部门id和哪个部门对应,所有没有出现在结果集中,这是内连接的一个特性。

也可以n张表进行连接,如在上面的例子进行扩充,求出每个员工的工作地点,需要连接三张表,只需用and连接上条件即可。

select *
from emp,dept,location
where emp.dept_id = dept.id and dept.location_id = location.id

二、多表查询的分类

关联查询可分为如下几类:

  • 等值连接和非等值连接
  • 自连接非自连接
  • 内连接外连接

我们需要根据需求去选择不同种类的连接查询

1.等值连接和非等值连接

等值连接就是前面的案例中,员工表的部门id与部门表的id呈现一个相等的状态,侧重于相等,所以叫等值连接。而非等值连接不是相等的情况。

来看一个非等值连接的情况:

如下两张表,需要求每个学生的成绩对应的等级

 代码如下:

select name,grade,level
from student,score
where student.grade between score.lowest_grade and score.greatest_grede

 该关联查询没有使用的关联条件不是=,而是其他的条件,被称为非等值连接。

2.自连接和非自连接

前面的员工表关联部门表进行查询就是非自连接,连接的其它表;而自连接就是连接当前表。

例子:上面的emp表有一个manager_id的字段,表示它的管理者id,同样的管理者同样也是员工,也是记录也在emp表中的,所以为了求出每个员工的管理者,就需要自连接:

select concat(e1.name,'为',e2.name,'工作')
from emp e1,emp e2
where e1.manager_id = e2.id

结果: 

自连接:当table1和table2本质上是同一张表,只是用取别名的方式虚拟成两张表以代表不同的意义。然后两个表再进行内连接,外连接等查询。

3.内连接和外连接

  • 内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行
  • 外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右)外连接。没有匹配的行时,结果表中相应的列为空(NULL)。

如果是左外连接,则连接条件中左边的表也称为主表 ,右边的表称为从表 。 如果是右外连接,则连接条件中右边的表也称为主表 ,左边的表称为从表 。

初步认识

在前面的例子中,我们使用到的是内连接:

#查询到所有员工的部门名,内连接的写法之一
SELECT emp.name,dept.name
from emp,dept
where emp.dept_id=dept.id

结果如下: 

 但是你会发现,少了个员工,这是因为该员工的部门id为空,在部门表中并没有相应的数据,又因为是内连接,所有该员工不会出现在结果里。

 要想解决该问题,就需要使用外连接。使员工表为主表,左外连接部门表:

得到的结果为:

 如果使用右外连接,结果为:

 也就是说部门表中所有的记录都会匹配出,尽管有些部门没有任何的员工,也列出来。

这是左外连接和右外连接的一个区别。

三、实现多表查询的语法

使用JOIN...ON子句创建连接的语法结构:

SELECT table1.column, table2.column,table3.column
FROM table1JOIN table2 ON table1 和 table2 的连接条件JOIN table3 ON table2 和 table3 的连接条件

语法说明:

  • 可以使用 ON 子句指定额外的连接条件。
  • 这个连接条件是与其它条件分开的。
  • ON 子句使语句具有更高的易读性。
  • 关键字 JOININNER JOIN、CROSS JOIN 的含义是一样的,都表示内连接。

1.内连接(INNER JOIN)的实现

语法:

SELECT 字段列表
FROM A表 INNER JOIN B表
ON 关联条件
WHERE 等其他子句;

例子:使用新的语法替换之前的查询员工操作,要求没有部门的员工不显示出来:

SELECT emp.name,dept.name
from emp
inner join dept
on emp.dept_id = dept.id

2.外连接(OUTER JOIN)的实现

2.1左外连接

语法:

#实现查询结果是A
SELECT 字段列表
FROM A表 LEFT OUTER JOIN B表
ON 关联条件
WHERE 等其他子句;

OUTER关键字可省略。

例子:查询所有员工的工作地点,没有部门的员工照样显示出来。

SELECT emp.name,dept.name,location.region
from emp left outer join dept
on emp.dept_id = dept.idleft join locationon dept.location_id = location.id

2.2右外连接(RIGHT OUTER JOIN)

语法:

SELECT 字段列表
FROM A表 RIGHT JOIN B表
ON 关联条件
WHERE 等其他子句;

例子:查询员工的部门信息,没有部门的员工不显示,但是把没有员工对应的部门也显示出来。

SELECT emp.name,dept.name
from emp right join dept
on emp.dept_id = dept.id

结果:

3.满外连接(FULL OUTER JOIN)

还有一种外连接结合了左外连接和右外连接的特点,称为满外连接:

  • 满外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据
  • SQL99是支持满外连接的。使用FULL JOIN 或 FULL OUTER JOIN来实现。
  • 需要注意的是,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT JOIN代替。

四、UNION的使用

合并查询结果

利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。

语法格式:

SELECT column,... FROM table1
UNION [ALL]
SELECT column,... FROM table2
  • UNION 操作符返回两个查询的结果集的并集,去除重复记录。
  • UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。

注意:执行UNION ALL语句时所需要的资源比UNION语句少。如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,则尽量使用UNION ALL语句,以提高数据查询的效率

举例1:查询部门编号>90或邮箱包含a的员工信息

#方式1
SELECT * FROM employees WHERE email LIKE '%a%' OR department_id>90
#方式2
SELECT * FROM employees WHERE email LIKE '%a%'
UNION
SELECT * FROM employees WHERE department_id>90;

举例2:使用union实现满外连接(下面内容会使用union all加速查找)

SELECT emp.name,dept.name
from emp left join dept
on emp.dept_id = dept.id
union
select emp.name,dept.name
from emp right join dept
on emp.dept_id = dept.id

结果: 

 

五、7种SQL JOINS的实现

下图是两种表的连接查询图,它们插叙的结果各不相同。图中红色部分代表最后查询的结果。

 

1.代码实现

  • 中图:内连接 A∩B,只取公共部分
select emp.name,dept.name
from emp inner join dept
on dept_id = dept.id
  • 左上图:左外连接,取左表的所有记录,并有条件的连接右表记录
select emp.name,dept.name
from emp left join dept
on dept_id = dept.id
  • 右上图:右外连接,取右表的所有记录,并有条件的连接左表记录
select emp.name,dept.name
from emp right join dept
on dept_id = dept.id
  • 左中图:A - A ∩ B
select emp.name,dept.name
from emp left join dept
on dept_id = dept.id
where dept.id is null   #去掉A∩B的部分
  • 右中图:B - A ∩ B
select emp.name,dept.name
from emp right join dept
on dept_id = dept.id
where emp.id is null   #或者dept_id is null
  • 左下图:是一个全连接,mysql不直接支持,但我们可以使用上面的union实现,但是根据上面的图,我们可以直接使用union all实现,增加效率。
    具体的:使用左上图 union all 右中图,或者右上图 union all 左中图都行。
select emp.name,dept.name   #左外连接取 A+(A∩B)
from emp left join dept
on emp.dept_id = dept.id
union all      #没有去重操作,效率高
select emp.name,dept.name   #右外连接取 B-(A∩B)
from emp right join dept
on emp.dept_id = dept.id
where emp.id is null
  • 右下图:A ∪B- A ∩ B
    使用左中图和右中图结合起来即可
select emp.name,dept.name   
from emp left join dept
on emp.dept_id = dept.id
where dept.id is null
union all
select emp.name,dept.name  
from emp right join dept
on emp.dept_id = dept.id
where emp.id is null

六、SQL99语法新特性

1.自然连接

SQL99 在 SQL92 的基础上提供了一些特殊语法,比如 NATURAL JOIN 用来表示自然连接。我们可以把自然连接理解为SQL92中的等值连接它会帮你自动查询两张连接表中所有相同的字段,然后进行等值连接

在SQL92标准中:

SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
AND e.`manager_id` = d.`manager_id`;

在 SQL99 中你可以写成:

SELECT employee_id,last_name,department_name
FROM employees e NATURAL JOIN departments d;

前提是字段名相同。

2.USING连接

当我们进行连接的时候,SQL99还支持使用 USING 指定数据表里的同名字段 进行等值连接。但是只能配合JOIN一起使用。比如:

SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING (department_id);

你能看出与自然连接 NATURAL JOIN 不同的是,USING 指定了具体的相同的字段名称,你需要在 USING 的括号 () 中填入要指定的同名字段。同时使用 JOIN...USING 可以简化 JOIN ON 的等值连接。它与下 面的 SQL 查询结果是相同的:

SELECT employee_id,last_name,department_name
FROM employees e ,departments d
WHERE e.department_id = d.department_id;

表连接的约束条件可以有三种方式:WHERE, ON, USING

  • WHERE:适用于所有关联查询
  • ON :只能和JOIN一起使用,只能写关联条件。虽然关联条件可以并到WHERE中和其他条件一起 写,但分开写可读性更好。
  • USING:只能和JOIN一起使用,而且要求两个关联字段在关联表中名称一致,而且只能表示关联字 段值相等

我们要控制连接表的数量 。多表连接就相当于嵌套 for 循环一样,非常消耗资源,会让 SQL 查询性能下降得很严重,因此不要连接不必要的表。在许多 DBMS 中,也都会有最大连接表的限制。


http://chatgpt.dhexx.cn/article/TReUa6ms.shtml

相关文章

SQL-多表关联查询详解

为了在工作中能更顺利的使用多表关联查询,今天这篇博客就写这个内容了。 在讲解多表关联查询之前,先生成测试表。 登录scott用户,运行以下语句生成测试表。 create table ex1 as select * from emp; create table ex2 as select * from dept…

Mysql如何对两张表的相同字段,同时查询两张数据表

前言 假设现在有两张数据表 表1如下: 表2如下: 表1和表2同时都再mysql的情况下,只有他们的uuid是一样的,其他字段信息不同,现在需要用sql语句根据uuid,同时将符合要求的数据查询出来,怎么做呢&…

SQL- join多表关联

一、SQL 连接(JOIN) 1、笛卡尔积 (1)当多张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是多张表条数的乘积 如A表15条(行)数据,B表20条(行)…

SQL语言多表关联查询

新建两张表: 表1:student 截图如下: 表2:course 截图如下: (此时这样建表只是为了演示连接SQL语句,当然实际开发中我们不会这样建表,实际开发中这两个表会有自己不同的主键。&…

[转载]静息态fMRI、DTI、VBM

[转载]静息态fMRI、DTI、VBM (2014-06-19 19:00:15) 转载▼ 标签: 转载 分类: fMRI-EEG 原文地址:静息态fMRI、DTI、VBM作者:426l 一、 简介 1、静息态fMRI数据处理学习内容 BOLD-fMRI技术自1990年发明至今,已经成…

用FSL进行VBM统计分析

用FSL进行VBM统计分析 总体步骤概览1.准备数据1.1 T1数据格式1.2 Template_list查看数据 2.剥头皮:fslvbm_1_bet3.数据分割生成模板:fslvbm_2_template4.后处理(标准化、调制、平滑):fslvbm_3_proc5.统计检验5.2查看结…

[spm操作] VBM分析中,modulation的作用

本帖作为 《用Matlab和SPM批量处理被试的经验总结》 的一部分 目录贴请见 http://home.52brain.com/forum.ph ... 1&extra#pid158525 在VBM分析中,通常都有一个modulation的选项,有些滴友对这个步骤的作用有点不太理解。 我先举一个例子&#xff…

不同的工具包对Voxel-based morphometry (VBM)计算结果的影响

​《本文同步发布于“脑之说”微信公众号,欢迎搜索关注~~》 前期大量的MRI研究已经表明,精神分裂患者很多脑区的局部灰质体积(regional grey matter volume)出现异常变化,但是这些研究的结果似乎并不一致。而这种结果…

如何提取差异脑区的灰质体积与临床量表算相关?——基于体素的形态学方法(VBM)

基于体素的形态学方法(VBM)是分析大脑解剖学(结构)差异最常用方法之一, 其通过给大脑volume逐体素打标签(分类)的方式来进行组织分割,过程高度自动化,比传统的基于ROI先验假设的分析方式得到的结果,更加具有稳定性和可重复性。VBM可以定量地测量出脑组织中各组织成分的…

VBM后的双样本t检验

上一篇文章写到做完了VBM,做完后因为数据一般都是患者组和HC组,这两个组之间需要进行比较,那么我们就要进行双样本t检验。 这里介绍双样本t检验的做法。 依然使用的是SPM-fMRI。 1.第一步是选择Specify 2nd-level 打开以后我们可以看到这个界…

VBM后的配对t检验以及xjview使用

之前写了VBM后的双样本t检验,再记录一下配对t检验。 配对t检验和双样本t检验的过程基本一致。包括以下三个步骤。 第一步输入两组被试时,应该成对输入,共有几个被试就有几个pair。 但是这里我在做的过程中没有加协变量,不知道会不…

Visual Basic

目录 一,Visual Basic 二,控制台程序 三,可视化程序 1,IDE 2,实例——加法计算器 一,Visual Basic Visual Basic是可视化的Basic,简称VB VB是第一个可视化编程语言。 二,控制…

VBM法MRI图像处理——记第一次使用cat12

1.环境 MATLAB 2015b SPM12 CAT12 2.SPM部分 命令行输入 spm 出现 以及 点击Toolbox 出现 3.CAT部分 点击上图 设置请根据自己需求 多分割了一种surface皮层数据,当做皮层统计分析SBM时需要提取surface皮层指标时会用到。 我本意只是获得灰质、白质的体积…

VBM_DARTEL算法对灰质变化的计算

根据一些文献得知,VBM目前比较新的算法是DARTEL算法,这一算法被集成在SPM里,这里记录一下做法。 VBM是对T1像进行分割得到灰质等。所以要有结构T1加权像数据。 整个流程应该是这样: 1.手动调整前联合(AC) …

基于cat12搞定VBM的ROI分析——vertex水平和ROI水平的双样本T检验

前言 本来上周要更新此篇的,但由于本身有问题没有解决清楚,再加上导师给了数据处理的任务下来了,两下耽搁,就等到现在了。上回说到,做了VBM和SBM的指标提取及双样本T检验的统计分析,那接下来我们还可以做什…

基于cat12和SPM12进行VBMSBM数据分析笔记1——数据预处理

前言 今年是小编步入研究生生活的第一年,研究方向待定,但主要以磁共振成像为主,以后会不断地总结这方面的知识,涉及MRI,数据分析基础方法理论,软件操作教程,文献阅读笔记总结等等,用…

基于cat12和SPM12进行大脑VBM数据分析笔记2——统计分析

小白一顿操作猛如虎——拿下VBM的双样本t检验 前言 培训的deadline到了,小编需要交作业了,所以就在此先把笔记记下来。作业需要提交一个报告,but这个报告我应该如何写呢,培训总结?哎,现在还是不清楚&…

磁共振影像分析之: 基于FSL的VBM分析(1)

磁共振影像分析之: 基于FSL的VBM分析(1) 基本概念 在开始之前, 先给出几个基本概念: 磁共振成像 磁共振成像(Magnetic Resonance Imaging, MRI)是一种基于核磁共振原理和射频波探测组织结构和功能的医学影像技术. 值得一提的是, 磁共振成像技术没有辐射, 对人体没有影响. …

MRI图像处理:VBM原理和步骤

VBM是voxel-based morphometry的缩写, 是对被试之间灰质体素粒度统计分析。VBM可以得到人群中volume和gyrification的不同,对clinical score进行相关性分析,VBM不仅仅可以用于结构数据(T1),还可以用在fmri和…