SQL进阶 | 外连接

概述

        外连接的进阶用法在行列转换中比较有优势,往往存在需要把数据库中的格式转换成报表格式,但是SQL仅仅只是查询数据的语言,格式转换并不是原本的用途。

全外连接

        标准 SQL 里定义了外连接的三种类型,如下所示。

  • 左外连接(LEFT OUTER JOIN)
  • 右外连接(RIGHT OUTER JOIN)
  • 全外连接(FULL OUTER JOIN)

        其中,左外连接和右外连接没有功能上的区别。用作主表的表写在运算符左边时用左外连接,写在运算符右边时用右外连接。相信这两种大家已经很熟悉了。在这三种里,全外连接相对来说使用较少。

 

        在这两张班级学生表里,田中和铃木同时属于两张表,而伊集院和西园寺只属于其中一张表。全外连接是能够从这样两张内容不一致的表里,没有遗漏地获取全部信息的方法,所以也可以理解成“把两张表都当作主表来使用”的连接。

-- 全外连接保留全部信息
select coalesce(a.id,b.id) as id,
				a.name as a_name,
				b.name as b_name
from class_a15 a full outer join class_b15 b
	on a.id = b.id;

-- 数据库不支持全连接
-- 使用左连接与右连接的并集
 SELECT A.id AS id,
 A.name AS A_name,
 B.name AS B_name
 FROM Class_A15 A left JOIN Class_B15 B
 ON A.id = B.id 
 union
 SELECT B.id AS id,
 A.name AS A_name,
 B.name AS B_name
 FROM Class_A15 A right JOIN Class_B15 B
 ON A.id = B.id;

用外连接进行集合运算

用外连接求差集 :A - B

 -- 用外连接求差集 :  A - B
 select a.id as id, a.name as a_name
 from class_a15 a left join class_b15 b
	on a.id = b.id
	where b.name is null;

用外连接求差集 :B- A

 -- 用外连接求差集: B - A
 select b.id as id,b.name as b_name
 from class_a15 a right join class_b15 b
	on a.id = b.id
where a.name is null;

用全外连接求异或集 

select a.id as id ,a.name as name
from class_a15 a left join class_b15 b on a.id = b.id
where a.name is null or b.name is null
union
select b.id as id ,b.name as name
from class_a15 a right join class_b15 b on a.id = b.id
where a.name is null or b.name is null

用外连接进行行列转换 (1)(行→列):制作交叉表

        这里有一张用于管理员工学习过的培训课程的表,如下所示。

        利用上面这张表生成下面这样一张交叉表(“课程学习记录一览表”)。○表示已学习过,NULL 表示尚未学习。

-- 使用外连接
select c0.name,
	case when c1.name is not null then 'O' else null end as "SQL入门",
	case when c2.name is not null then 'O' else null end as "UNIX基础",
	case when c3.name is not null then 'O' else null end as "Java中级"
from (select distinct name from courses) c0  -- 这里的c0是侧栏
left outer join (select name from courses where course = 'SQL入门') c1 on c0.name = c1.name
left outer join (select name from courses where course = 'UNIX基础') c2 on c0.name = c2.name
left outer join (select name from courses where course = 'Java中级') c3 on c0.name = c3.name;

        使用子查询,根据源表 Courses 生成 C0 ~ C3 这 4 个子集。C0 包含了全部员工,起到了“员工主表”的作用。C1 ~ C3 是每个课程的学习者的集合。这里以 C0 为主表,依次对 C1 ~ C3 进行外连接操作。如果某位员工学习过某个课程,则相应的课程列会出现他的姓名,否则为 NULL。最后,通过 CASE 表达式将课程列中员工的姓名转换为○就算完成了。

        但是因为大量用到了内嵌视图和连接操作,代码会显得很臃肿。而且,随着表头列数的增加,性能也会恶化。

-- 水平展开2:使用标量子查询
select c0.name,
	(select 'O' from courses c1 where course = 'SQL入门' and c1.name = c0.name) as "SQL入门",
	(select 'O' from courses c2 where course = 'UNIX基础' and c2.name = c0.name) as 'UNIX基础',
	(select 'O' from courses c3 where course = 'Java中级' and c3.name = c0.name) as "Java中级"
from (select distinct name from courses) c0; -- 这里的c0是表侧栏

-- 水平展开 3:嵌套使用case表达式
select name,
	case when sum(case when course = 'SQL入门' then 1 else null end) = 1
				then 'O' else null end as "SQL入门",
	case when sum(case when course = 'UNIX基础' then 1 else null end) = 1
				then 'O' else null end as "UNIX基础",
	case when sum(case when course = 'Java中级' then 1 else null end) = 1
				then 'O' else null end as "Java中级"
from courses
group by name;

 用外连接进行行列转换 (2)(列→行):汇总重复项于一列

        假设存在下面这样一张表。

 

select employee,child_1 as child from personnel
union all
select employee,child_2 as child from personnel
union all
select employee,child_3 as child from personnel;

 

        因为 UNION ALL 不会排除掉重复的行,所以即使吉田没有孩子,结果里也会出现 3 行相关数据。所以对结果再次优化。先创建一个视图,保存所有的子女列表。然后用员工表作为主表与该视图进行外连接,当员工表中的孩子1-3存在于视图中,返回该名字,否则返回null。

-- 生成一个存储子女列表的视图
create view children(child)
as select child_1 from personnel
		union
		select child_2 from personnel
		union
		select child_3 from personnel;
-- 获取员工子女列表的SQL语句(没有孩子的员工也要输出)
select emp.employee,children.child
from personnel emp
left outer join children on children.child in (emp.child_1,emp.child_2,emp.child_3);

在交叉表里制作嵌套式表侧栏

        在生成统计表的工作中,经常会有制作嵌套式表头和表侧栏的需求。例如这道例题:表 TblPop 是一张按照县、年龄层级和性别统计的人口分布表,要求根据表 TblPop 生成交叉表“包含嵌套式表侧栏的统计表”。

使用交叉连接对tblage和tblsex生成笛卡尔积作为主表,和tblpop进行外连接按照年龄区间和性别分组统计人数和。

-- 使用外连接生成嵌套式表侧栏
select master.age_range as age_class,
				master.sex as sex_acd,
				data.pop_tohoku as pop_tohoku,
				data.pop_kanto as pop_kanto
from (select age_class,age_range,sex_cd,sex
			from tblage cross join tblsex) master -- 使用交叉连接生成两张主表的笛卡尔积
left outer join (select age_class,sex_cd,
										sum(case when pref_name in ('青森','秋田') then population else null end) as pop_tohoku,
										sum(case when pref_name in ('东京','千叶') then population else null end) as pop_kanto
									from tblpop
									group by age_class,sex_cd) data
	on master.age_class = data.age_class and master.sex_cd = data.sex_cd;	

总结

  • SQL 不是用来生成报表的语言,所以不建议用它来进行格式转换。
  • 必要时考虑用外连接或 CASE 表达式来解决问题。
  • 生成嵌套式表侧栏时,如果先生成主表的笛卡儿积再进行连接,很容易就可以完成。
  • 从行数来看,表连接可以看成乘法。因此,当表之间是一对多的关系时,连接后行数不会增加。
  • 外连接的思想和集合运算很像,使用外连接可以实现各种集合运算。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于ssm生活缴费系统及相关安全技术的设计与实现论文

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对生活缴费信息管理混乱,出错率高,信息安全性差…

HTTP/2 快速重置 DDOS 漏洞几乎影响所有网站

一种新形式的DDOS的细节,它需要相对最少的资源来发起前所未有的规模的攻击,这使得网站成为一个明显的危险,因为服务器软件公司竞相发布补丁来防范它。 HTTP/2 快速重置漏洞 该漏洞利用了 HTTP/2 和 HTTP/3 网络协议,这些协议允许…

JavaScipt验证URL新方法(2023 年版)

JavaScript诞生以来,一直没有一种简单的方法验证URL,现在JavaScript新增了一个新方法——URL.canParse。 URL.canParse(https://www.stefanjudis.com); // true URL.canParse(www.stefanjudis.com); // falseURL.canParse() 是一种快速验证字符串是否为…

开源 Serverless 框架 Laf 性能优化实践

介绍 Laf 是一个完全开源的 Serverless 框架,Laf 的 Node.js 运行时容器 (以下简称为 Runtime) 是 Laf 的函数执行环境,依托于 Express.js 框架。采用容器进程常驻的方式,每一个应用对应于一个或多个容器 (弹性伸缩下),底层使用了…

雅典娜Athena-signa音频算法源码与麦克风阵列角度定义互换问题

雅典娜Athena-signa音频算法源码与麦克风阵列角度定义互换问题 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 1 dios_ssp_doa_api.c 2 公…

网站提示不安全

当我们在浏览网站时,可能会遇到浏览器提示网站不安全的情况。这种提示可能源于网站缺乏有效的SSL证书,从而导致用户的个人信息和数据容易受到攻击和窃取。当网站使用SSL证书时,浏览器会显示一个小锁图标,并且网站的URL会以“https…

SQLMAP的使用(rails 为例)

1.启动一个项目&#xff0c;例如rails学习的项目&#xff0c;修改config/database.yml&#xff0c; 假设来一个接口&#xfeff; class YourModel::YourController < ApplicationController def test_sqlisql "select * from your_table_name where id " par…

手写数组去重

说明:以下代码如有考虑不周的bug请评论区留言,我将不断完善或者优化,谢谢 一、看结果 1.执行代码 const arr = [{ id: 1, name: "数据1" },{ id: 1, name: "数据2" },{ id: 2, name: "数据3" },{ id: 3, name: "数据4" },{ id: …

磁盘坏道修复工具-是一款非常方便实用的磁盘坏道修复软件-供大家学习研究参考

1、支持磁盘数据擦除。 2、杜绝因硬盘坏道&#xff0c;而产生个人隐私数据泄露的问题。 3、支持对该磁盘格式化。 下载&#xff1a;https://download.csdn.net/download/weixin_43097956/88625682

解决Java中GB2312字符集缺失的汉字乱码问题

最近在做一个读取CSV文件&#xff0c;解析其中数据并入库的功能&#xff0c;使用的是OpenCSV组件&#xff0c;CSV文件字符集是GB2312&#xff0c;读取文件流时使用的也是GB2312字符集&#xff0c;但最终测试结果发现写入数据库的中文中存在乱码&#xff0c;奇怪的是同一个字段中…

YOLOv8算法改进【NO.93】使用resnet18网络作为主干特征提取网络

前 言 YOLO算法改进系列出到这&#xff0c;很多朋友问改进如何选择是最佳的&#xff0c;下面我就根据个人多年的写作发文章以及指导发文章的经验来看&#xff0c;按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通&#xff1a; 第一…

大数据云计算——Docker环境下部署Hadoop集群及运行集群案列

大数据云计算——Docker环境下部署Hadoop集群及运行集群案列 本文着重介绍了在Docker环境下部署Hadoop集群以及实际案例中的集群运行。首先&#xff0c;文章详细解释了Hadoop的基本概念和其在大数据处理中的重要性&#xff0c;以及为何选择在Docker环境下部署Hadoop集群。接着&…

致远互联-OA wpsAssistServlet 任意文件读取漏洞复现

0x01 产品简介 致远互联-OA 是数字化构建企业数字化协同运营中台,面向企业各种业务场景提供一站式大数据分析解决方案的协同办公软件。 0x02 漏洞概述 致远互联-OA wpsAssistServlet 存在任意文件读取漏洞,攻击者可读取系统密码等敏感信息进一步控制系统。 0x03 复现环境…

【开源】基于JAVA语言的农家乐订餐系统

项目编号&#xff1a; S 043 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S043&#xff0c;文末获取源码。} 项目编号&#xff1a;S043&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户2.2 管理员 三、系统展示四、核…

陈可之艺术履历

陈可之&#xff0c;中国著名艺术家。国家一级美术师&#xff0c;获国务院政府津贴&#xff0c;中国农工民主党中央书画院院长&#xff0c;北京市政府文史馆馆员&#xff0c;东方油画院院长&#xff0c;北京东方书画研究会会长 &#xff0c;中国国际书画艺术研究会副会长&#x…

部署Kubernetes(k8s)集群,可视化部署kuboard

所需机器 主机名地址角色配置k8s-master192.168.231.134主节点2核4G,centos7k8s-node1192.168.231.135工作节点2核4G,centos7k8s-node2192.168.231.136工作节点2核4G,centos7 主节点CPU核数必须是 ≥2核且内存要求必须≥2G&#xff0c;否则k8s无法启动 1. 集群环境部署【三台…

40G AOC线缆全系列产品知识详解

40G AOC&#xff08;Active Optical Cable&#xff09;线缆作为高速数据传输的重要组成部分&#xff0c;在现代通信和数据中心应用中扮演着重要角色。本期文章我们将从其基本原理、应用领域、优势特点等方面对ETU-LINK 40G AOC全系列产品进行解析。 一、40G AOC全系列产品解析…

Windows Server C盘空间不足怎么办?

Windows Server 2016/2019/2022中占用C盘空间的主要内容为&#xff1a;分页文件、休眠文件、临时文件、备份文件、浏览器下载文件等&#xff0c;随着计算机使用时间的增长&#xff0c;这些文件也会逐渐增多&#xff0c;从而导致C盘驱动器爆满而导致系统运行缓慢而崩溃。那么&am…

Java监听器与观察者模式

Java监听器与观察者模式 Java中的监听器&#xff08;Listener&#xff09;和观察者模式&#xff08;Observer Pattern&#xff09;都是用于处理对象间的事件通知和响应的设计模式。它们的目的是在对象之间建立一种松散的耦合&#xff0c;使得一个对象的状态变化可以通知到其他…

1311:【例2.5】求逆序对 归并排序

1311&#xff1a;【例2.5】求逆序对 【题目描述】 给定一个序列a1,a2,…,an&#xff0c;如果存在i<j并且ai>aj&#xff0c;那么我们称之为逆序对&#xff0c;求逆序对的数目。 【输入】 第一行为n,表示序列长度&#xff0c;接下来的n行&#xff0c;第i1行表示序列中的第…