五种主流数据库:连接查询

关系型数据库通常将不同的实体对象和它们之间的联系存储在多个表中,例如电商系统中使用的产品表、用户表、订单表以及订单明细表等。当我们查看某个订单信息时,需要同时从这几个表中查找关于该订单的相关数据。

本文比较五种主流数据库实现的多表连接查询功能,包括 MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite。

功能MySQLOracleSQL ServerPostgreSQLSQLite
内连接✔️✔️✔️✔️✔️
左外连接✔️✔️✔️✔️✔️
右外连接✔️✔️✔️✔️✔️
全外连接✔️✔️✔️✔️
交叉连接✔️✔️✔️✔️✔️
自然连接✔️✔️✔️✔️
自连接✔️✔️✔️✔️✔️

连接的语法与类型

在 SQL 标准的发展过程中产生了两种连接查询语法:

  • ANSI SQL/86 标准使用 FROM 和 WHERE 子句指定表的连接查询。
  • ANSI SQL/92 标准使用 JOIN 和 ON 子句指定表的连接查询。

下面我们分别介绍这两种连接查询语法。

员工表(employee)中存储了员工的信息和员工所在部门的编号,同时部门的信息存储在部门表(department)中。如果我们想要知道某个员工所在部门的名称,就需要同时查询员工表和部门表。以下示例使用 FROM 和 WHERE 子句实现了这两个表的连接查询:

SELECT d.dept_id, e.dept_id, d.dept_name, e.emp_name
FROM employee e, department d
WHERE e.dept_id = d.dept_id
AND e.emp_id = 1;

其中,FROM 子句用于指定查询的表,逗号表示连接两个表。WHERE 子句既指定了过滤条件(e.emp_id=1),又指定了连接两个表的条件(e.dept_id= d.dept_id),也就是员工表中的部门编号等于部门表中的编号。另外,我们在查询中还通过表别名(e 和 d)指明了字段来自哪个表。该查询返回的结果如下:

dept_id|dept_id|dept_name|emp_name
-------|-------|---------|--------1|      1|行政管理部 |刘备 

通过使用部门编号作为连接查询的条件,我们同时获得了员工和员工所在部门的信息。

对于以上连接查询示例,我们同样可以使用 JOIN 和 ON 子句实现:

SELECT d.dept_id, e.dept_id, d.dept_name, e.emp_name
FROM employee e
JOIN department d ON (e.dept_id = d.dept_id)
WHERE e.emp_id = 1;

其中,JOIN 子句表示连接员工表和部门表,ON 子句指定了连接两个表的条件,WHERE 子句指定了查询的过滤条件。查询返回的结果和上面的示例相同。

💡推荐使用 JOIN 和 ON 子句进行连接查询,因为这种方式的语义更明确,更符合 SQL 的声明性。对于 FROM 和 WHERE 连接查询语法,WHERE 子句同时用于指定查询的过滤条件和表的连接条件,逻辑显得比较混乱。另外,并不是所有的连接查询类型都支持 FROM 和 WHERE 连接查询的语法。

SQL 支持的连接查询包括内连接、外连接、交叉连接、自然连接以及自连接等。其中,外连接又可以分为左外连接、右外连接以及全外连接。下面我们详细介绍一下 SQL 中的各种连接类型。

内连接

内连接(Inner Join)查询返回两个表中满足连接条件的数据。内连接使用关键字 INNER JOIN 表示,也可以简写成 JOIN。内连接的原理如下图所示(连接条件为两个表的 id 相等)。

在这里插入图片描述
其中 id 等于 1 和 3 的记录是两个表中满足连接条件的数据,因此内连接返回了这 2 个记录。

等值连接

连接查询中的 ON 子句与 WHERE 子句类似,可以支持各种条件运算符。其中最常用的是等号(=)运算符,这种连接查询也被称为等值连接。例如:

SELECT e.emp_name AS "员工姓名", j.job_title "职位名称"
FROM employee e
JOIN job j ON (e.job_id = j.job_id)
WHERE e.emp_id = 1;

我们通过职位编号连接了员工表和职位表,查询返回的结果如下:

员工姓名|职位名称
-------|-------刘备 |总经理

等值连接返回两个表中连接字段值相等的数据,我们最常使用的连接就是等值连接。

非等值连接

除等号运算符外,连接条件中也可以使用其他比较运算符或者逻辑运算符,例如>=、!=、BETWEEN、AND 等,这种连接查询被称为非等值连接。例如:

SELECT e.emp_name AS "员工姓名", e.salary "月薪"
FROM employee e
JOIN job j ON (e.job_id != j.job_id AND e.salary BETWEEN j.min_salary AND j.max_salary)
WHERE j.job_title = '开发经理';

我们将职位编号不相等以及员工的月薪位于“开发经理”月薪的范围之内作为连接条件,返回当前月薪属于开发经理级别但不是开发经理的员工。查询返回的结果如下:

员工姓名|月薪 
-------|--------孙尚香 |12000.00

“孙尚香”的月薪位于开发经理级别,但是她的实际职位是财务经理。

外连接

外连接查询可以分为左外连接、右外连接以及全外连接。

左外连接

左外连接(Left Outer Join)查询首先返回左表中的全部数据。之后,如果右表中存在满足连接条件的数据,就返回该数据;如果没有相应的数据,就返回空值。左外连接使用关键字 LEFT OUTER JOIN 表示,也可以简写成 LEFT JOIN。左外连接的原理如下图所示(连接条件为两个表的 id 相等)。

在这里插入图片描述
其中,id 等于 2 的记录只存在表 table1 中。左外连接仍然会返回左表中的记录;而对于右表 table2 中的 price 字段,则返回了空值。

如果我们想要统计每个部门中的员工人数。考虑到某些部门可能还没有员工入职,使用内连接无法显示这些部门,此时我们可以使用左外连接查询。例如:

SELECT d.dept_name AS "部门名称", count(e.emp_id) AS "员工人数"
FROM department d
LEFT JOIN employee e ON (e.dept_id = d.dept_id)
GROUP BY d.dept_name;

其中,LEFT JOIN 表示左外连接,连接条件为两个表中的部门编号相等。查询返回的结果如下:

部门名称 |员工人数
--------|-------
行政管理部| 3
人力资源部| 3财务部 | 2研发部 | 9销售部 | 8保卫部 | 0

虽然“保卫部”目前还没有任何员工,但是查询结果仍然返回了该部门。

如果我们想要找出哪些部门没有员工,可以在以上左外连接的基础上增加一个过滤条件:

SELECT d.dept_id AS "部门编号",d.dept_name AS "部门名称"
FROM department d
LEFT JOIN employee e ON (e.dept_id = d.dept_id)
WHERE e.emp_id IS NULL;

左外连接返回了所有的部门信息。如果某个部门没有员工,对应的 e.emp_id 字段就是空值。查询返回的结果如下:

部门编号|部门名称
-------|-------6|保卫部

另外,只有 Oracle 实现了 ANSI SQL/86 标准的左外连接语法。例如:

-- Oracle
SELECT d.dept_id AS "部门编号",d.dept_name AS "部门名称"
FROM department d, employee e
WHERE d.dept_id = e.dept_id(+)
AND e.emp_id IS NULL;

其中,WHERE 子句右侧的(+)运算符表示右表中可能缺少相应的数据,也就表示这是一个左外连接查询。

右外连接

右外连接(Right Outer Join)查询首先返回右表中的全部数据。如果左表中存在满足连接条件的数据,就返回该数据;如果没有相应的数据,就返回空值。右外连接使用关键字 RIGHT OUTER JOIN 表示,也可以简写成 RIGHT JOIN。右外连接的原理如下图所示(连接条件为两个表的 id 相等)。

在这里插入图片描述
其中,id 等于 5 的数据只存在表 table2 中。右外连接仍然会返回右表中的记录;而对于左表 table1 中的 name 字段,则返回了空值。简而言之:

table1 RIGHT JOIN table2

等价于:

table2 LEFT JOIN table1

右外连接和左外连接可以相互转换。因此,前面统计员工人数的示例也可以使用等价的右
外连接查询实现:

SELECT d.dept_name AS "部门名称", count(e.emp_id) AS "员工人数"
FROM employee e
RIGHT JOIN department d ON (e.dept_id = d.dept_id)
GROUP BY d.dept_name;

其中,RIGHT JOIN 表示右外连接,连接条件是两个表中的部门编号相等。

另外,在 Oracle 中也可以使用 ANSI SQL/86 标准的右外连接语法:

-- Oracle
SELECT d.dept_name AS "部门名称", count(e.emp_id) AS "员工人数"
FROM department d, employee e
WHERE e.dept_id(+) = d.dept_id
GROUP BY d.dept_name;

注意查询条件中(+)运算符所在的位置。

全外连接

全外连接(Full Outer Join)查询相当于左外连接加上右外连接。查询同时返回左表和右表中所有的数据。如果右表或者左表中存在满足连接条件的数据,就返回该数据;如果没有相应的数据,就返回空值。全外连接使用关键字 FULL OUTER JOIN 表示,也可以简写成 FULL JOIN。

全外连接的原理如下图所示(连接条件为两个表的 id 相等)。

在这里插入图片描述
查询结果包含了两个表中所有的 id。对于左表中不存在的数据(id=5)以及右表中不存在的数据(id=2)。分别为相应的字段返回了空值。

假如公司组织了一次活动,需要将所有的员工进行分组。每个组的信息存储在表 t_group 中,员工的分组信息存储在 t_emp_group 中。现在我们想要知道哪些组还没有分配员工,以及哪些员工还没有被分配到任何组。为此,我们可以使用全外连接查询:

-- Oracle、Microsoft SQL Server、PostgreSQL 以及 SQLite
SELECT g.group_name, eg.emp_id
FROM t_group g
FULL JOIN t_emp_group eg ON (eg.group_id = g.group_id)
WHERE g.group_id IS NULL OR eg.emp_id IS NULL;

我们使用两个表中的 group_id 字段作为连接条件,同时在 WHERE 子句中指定了想要返回的数据。查询返回的结果如下:

group_name|emp_id
----------|------| 8| 12| 16| 20| 23五组 | 

查询结果显示“五组”还没有分配任何员工,工号为 8、12、16、20 以及 23 的员工还没有被分配到任何组。

MySQL 目前不支持全外连接。

另外,ANSI SQL/86 标准语法不支持全外连接。

交叉连接

交叉连接也被称为笛卡儿积(Cartesian Product),使用关键字 CROSS JOIN 表示。两个表的交叉连接将一个表的所有数据行和另一个表的所有数据行进行两两组合,返回结果的数量为两个表中的行数相乘。例如,一个 100 行数据的表和一个 200 行数据的表进行交叉连接查询将会产生 20 000 行数据。交叉连接的原理如下图所示:

在这里插入图片描述

table1 中存在 3 条记录,table2 中也存在 3 条记录,因此这两个表交叉连接的结果总共包含 9 条记录。交叉连接使用的场景比较少,一般用于生成大量测试数据。

我们介绍一个利用交叉连接生成数字序列的方法,首先创建一个示例表 t_number:

CREATE TABLE t_number(n INTEGER PRIMARY KEY);
INSERT INTO t_number VALUES (0);
INSERT INTO t_number VALUES (1);
INSERT INTO t_number VALUES (2);
INSERT INTO t_number VALUES (3);
INSERT INTO t_number VALUES (4);
INSERT INTO t_number VALUES (5);
INSERT INTO t_number VALUES (6);
INSERT INTO t_number VALUES (7);
INSERT INTO t_number VALUES (8);
INSERT INTO t_number VALUES (9);

t_number 表中存储了数字 0~9。我们在以下查询中将 t_number 表多次和它自己进行交叉连接:

SELECT hundrand.n * 100 + ten.n * 10 + one.n AS n
FROM t_number hundrand
CROSS JOIN t_number ten
CROSS JOIN t_number one
ORDER BY n;

查询返回的结果如下:

n 
---0123
...
997
998
999

查询返回了一个 0~999 的数字序列。显然,我们可以通过更多的自连接生成更大的数字序列。

对于 ANSI SQL/86 标准,交叉连接指的是不指定表的连接条件。例如:

SELECT hundrand.n * 100 + ten.n * 10 + one.n AS n
FROM t_number hundrand, t_number ten, t_number one
ORDER BY n;

💡如果表中的数据量比较大,交叉连接可能会导致查询结果的数据量急剧膨胀,从而引起性能问题。我们通常应该指定连接条件,避免产生交叉连接。

自然连接

如果连接查询同时满足以下条件,我们可以使用 USING 替代 ON 来简化连接条件的输入:

  • 连接条件是等值连接。
  • 两个表中的连接字段名称相同,类型也相同。

例如,上文中的等值连接查询可以使用 USING 关键字简化如下:

-- Oracle、MySQL、PostgreSQL 以及 SQLite
SELECT e.emp_name AS "员工姓名", j.job_title "职位名称"
FROM employee e
JOIN job j USING (job_id)
WHERE e.emp_id = 1;

其中,USING 表示使用两个表中的公共字段(job_id)进行等值连接。另外,查询语句中出现的公共字段无须添加表名限定。

除 Microsoft SQL Server 外,其他 4 种数据库都支持 USING 关键字。

进一步来说,如果等值连接条件中包含了两个表中所有同名同类型的字段,查询语句可以继续进行简化。例如,员工表和职位表中只存在 1 个同名同类型的字段(job_id),因此上面的示例可以进一步修改为下面这样:

-- Oracle、MySQL、PostgreSQL 以及 SQLite
SELECT e.emp_name AS "员工姓名", j.job_title "职位名称"
FROM employee e
NATURAL JOIN job j
WHERE e.emp_id = 1 
AND job_id = 1;

其中,NATURAL JOIN 表示自然连接,我们同时省略了连接条件,表示使用两个表中的所有同名同类型字段进行等值连接。

同样,除 Microsoft SQL Server 外的其他 4 种数据库都支持自然连接。

自连接

自连接(Self Join)查询是指一个表和它自己进行连接查询。自连接本质上并没有什么特殊之处,主要用于处理那些对自身进行了外键引用的表。例如,员工表中的经理字段(manager)引用了员工表自身的编号字段(emp_id)。如果我们想要查看员工以及他的经理,可以通过自连接查询实现:

SELECT e.emp_name AS "员工姓名",m.emp_name AS "经理姓名"
FROM employee e
LEFT JOIN employee m ON (m.emp_id = e.manager)
WHERE e.emp_id = 9;

由于自连接中同一个表(employee)出现了两次,我们必须使用表别名进行区分。其中别名 e 代表了员工,别名 m 代表了经理。查询返回的结果如下:

员工姓名|经理姓名
-------|-------赵云 |刘备 

另外,我们在查询中使用了左外连接,因为员工表中存在没有上级经理的员工(刘备)。

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

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

相关文章

第3章 数据链路层(3)

3.6 局域网 采用广播信道 3.6.1 局域网的基本概念和体系结构 特点: ①覆盖范围小②专门通信介质【双绞线,同轴电缆】③通信延时短,误码率低,可靠性高。④通信质量好。因此采用无确认,无连接的服务。⑤关系平等,共享信道⑥分布式控制,广播信道,广播,组播 决定因素: ①拓扑结构:…

MuJoCo 入门教程(八)Model仓库

系列文章目录 前言 一、MuJoCo 动物园 一个物理仿真器的好坏取决于它所仿真的模型,而在像 MuJoCo 这样功能强大、建模选项众多的仿真器中,很容易创建出行为与预期不符的 "坏 "模型。MuJoCo Menagerie 的目标是为社区提供一个设计精良、开箱即用…

【学习笔记】R语言入门与数据分析1

数据分析 数据分析的过程: 数据采集 数据存储 数据分析 数据挖掘 数据可视化 进行决策 数据挖掘 数据量大 复杂度高,容忍一定的误差限 追求相关性而非因果性 数据可视化 直观明了 R语言介绍 R是免费的(开源软件、扩展性好)…

家居颜色搭配6大法则,奶油风配色指南。福州中宅装饰,福州装修

奶油风装修的配色主要以奶油色系为主,搭配其他低饱和度的色彩,营造出一种温馨、柔和的氛围。以下是一些常见的奶油风装修配色法则: 1. 主色:奶油色 奶油色是奶油风装修的主色调,通常使用在墙面、地面、家具等大面积的…

如何从0开始构建GPT模型?

OpenAI 推出强大的生成式预训练转换器 (GPT) 语言模型,为自然语言处理 (NLP) 开辟了新的领域。将 GPT 模型集成到虚拟助手和聊天机器人中可以增强它们的能力,这导致对 GPT 模型的需求激增。根据 Allied Mar…

软考122-上午题-【软件工程】-需求分析

一、软件需求 在进行需求获取之前,首先要明确需要获取什么,也就是需求包含哪些内容。 软件需求是指用户对目标软件系统在功能、行为、性能、设计约束等方面的期望。通常,这些需求包括功能需求、性能需求、用户或人的因素、环境需求、界面需…

Android开发之移除权限

Android开发之移除权限 在Android开发结束后,我们将build好的App Bundle上传至Google Play。这时Google可能会提示一些需要解决的错误,比如xx权限需要限制,需要解释为什么需要这些权限,需要添加文字描述和视频链接,但…

SOCKS代理是如何提高网络性能和兼容性的?

SOCKS代理作为一种网络协议中间件,不仅在提升网络隐私和安全性方面发挥着重要作用,也在提高网络性能和兼容性方面有着不容忽视的影响🚀。本文将深入探讨SOCKS代理如何通过减少网络延迟🚀、优化数据传输🔄、提高跨平台兼…

【智能算法应用】灰狼算法求解TSP问题

目录 1.算法原理2.TSP数学模型3.结果展示4.参考文献 1.算法原理 【智能算法】灰狼算法(GWO)原理及实现 2.TSP数学模型 旅行商问题(TSP)是一种著名的组合优化问题,它涉及寻找给定一组城市及其之间的距离或成本&#…

查询卖家已卖出的交易数据

要获取淘宝订单详情数据,你需要使用淘宝开放平台的API来获取数据。以下是获取淘宝订单详情数据的步骤: 在淘宝开放平台上创建一个应用,获取到AppKey和AppSecret。 使用OAuth 2.0授权方式,获取到授权码。 第三方公司授权 使用授…

kaggle 泰坦尼克号1(根据男女性存活率)

kaggle竞赛 泰坦尼克号 流程 下载kaggle数据集导入所要使用的包引入kaggle的数据集csv文件查看数据集的大小和长度去除冗余数据建立特征工程导出结果csv文件 1.下载kaggle数据集 2.导入所要使用的包 import pandas as pd import numpy as np import matplotlib.pyplot as …

【MATLAB源码-第185期】基于matlab的16QAM系统相位偏移估计EOS算法仿真,对比补偿前后的星座图误码率。

操作环境: MATLAB 2022a 1、算法描述 1. 引言 M-QAM调制技术的重要性 现代通信系统追求的是更高的数据传输速率和更有效的频谱利用率。M-QAM调制技术,作为一种高效的调制方案,能够通过在相同的带宽条件下传输更多的数据位来满足这一需求…

英飞凌TC3xx SMU再述

目录 1. Safety和Security 2.SMU概述 2.1 为什么设计SMU 2.2 SMU整体框架 2.3 SMU Alarm配置 2.4 SMU状态机 3.小结 1. Safety和Security SMU是英飞凌TC3xx系列功能安全架构里最重要的组成部分,用于管理MCU故障状态下的行为。 但在聊SMU之前,我…

数据结构笔记

重点 一、数据结构的定义 逻辑结构 集合结构:除了同属于一个集合之外,没有其他关系 线状结构:数据元素之间是一对一的关系 树形结构:数据元素之间是一对多的层次关系 图形结构:数据元素之间是多对多的关系 存储…

VRTK_强制瞬移/传送

VRTK_强制瞬移/传送 前言配置代码 前言 在使用VRTK制作虚拟仿真项目的时候,会遇到强制头盔至目标点的功能 VRTK内有封装好的移动方法。 VRTK_BasicTeleport脚本内的方法ForceTeleport() 配置 需要配置的传送组件 代码 本文代码是直接可以其他脚本调用&#x…

springboot在使用 Servlet API中提供的javax.servlet.Filter 过滤器 对请求参数 和 响应参数 进行获取并记录日志方案

不多说 直接上代码 第一步 package com.xxx.init.webFilter;import com.alibaba.fastjson.JSONObject; import com.xxx.api.constant.CommonConstant; import com.xxx.api.entities.log.OperationLog; import com.xxx.init.utils.JwtHelper; import com.xxx.init.utils.Reques…

antd+Vue 3实现table行内upload文件图片上传【超详细图解】

目录 一、背景 二、效果图 三、代码 一、背景 一名被组长逼着干前端的苦逼后端&#xff0c;在一个晴天霹雳的日子&#xff0c;被要求前端订单产品实现上传产品图片并立刻回显图片。 二、效果图 三、代码 <template><a-table :dataSource"dataSource" :c…

如何使用固定公网地址SSH远程访问本地内网openEuler系统

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系…

【图论】Dijkstra单源最短路径-朴素方法-简单模板(迪杰斯特拉算法)

Dijkstra单源最短路径 问题描述 输入n 表示n个结点&#xff0c;m表示m条边&#xff0c;求编号1的结点到每个点的最短路径 输出从第一个点到第n个点的最短路径 思路 将图g[][]中所有的权值初始化为0x3f表示正无穷 将dist[]中所有的值初始化为0x3f表示从第一个点到所有点的距离…

NX/UG二次开发—CAM—一些外挂刀路选择方案对比

在做一刀轨编辑工具时&#xff0c;大家希望实现类似NX刀轨编辑中选择刀路的功能&#xff0c;以下我罗列了几种目前外挂里使用的几种方式&#xff0c;自己也做了一些对比&#xff1a; 涉及一些运算时间&#xff0c;参考电脑配置(内存32G&#xff0c;CPUi9-12950HX) 1、刀路转成…