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 bon a.id = b.id;-- 数据库不支持全连接
-- 使用左连接与右连接的并集SELECT A.id AS id,A.name AS A_name,B.name AS B_nameFROM Class_A15 A left JOIN Class_B15 BON A.id = B.id unionSELECT B.id AS id,A.name AS A_name,B.name AS B_nameFROM Class_A15 A right JOIN Class_B15 BON A.id = B.id;

用外连接进行集合运算

用外连接求差集 :A - B

 -- 用外连接求差集 :  A - Bselect a.id as id, a.name as a_namefrom class_a15 a left join class_b15 bon a.id = b.idwhere b.name is null;

用外连接求差集 :B- A

 -- 用外连接求差集: B - Aselect b.id as id,b.name as b_namefrom class_a15 a right join class_b15 bon 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) = 1then 'O' else null end as "SQL入门",case when sum(case when course = 'UNIX基础' then 1 else null end) = 1then 'O' else null end as "UNIX基础",case when sum(case when course = 'Java中级' then 1 else null end) = 1then '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 personnelunionselect child_2 from personnelunionselect 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,sexfrom 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_kantofrom tblpopgroup by age_class,sex_cd) dataon master.age_class = data.age_class and master.sex_cd = data.sex_cd;	

总结

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

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

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

相关文章

SpringBoot - application.yml 多环境切换解决方案

问题描述 这个问题玩过 SpringCloud 的小伙伴估计会想到用 bootstrap.yml 来解决这个问题。但是如果说为了解决这个问题引入了一堆的 SpringCloud Jar,就感觉杀鸡用牛刀。 于是今天我们想只有 application.yml 自己就可以解决这个问题,如何搞定&#x…

nginx常用命令及配置文件说明

目录 1 前言2 nginx常用命令2.1 查看 Nginx 版本号2.2 启动 Nginx2.3 停止 Nginx2.4 重新加载 Nginx 配置 3 Nginx配置文件说明3.1 **全局块**3.2 **Events 块**3.3 **HTTP 块** 4 结语 1 前言 使用 Nginx 作为 Web 服务器是构建现代网络基础架构的关键一环。在运维和开发领域…

kettle+report designer导出带样式的excel包含多个sheet页

场景介绍: 运用pentaho report designer报表设计器,查询数据库字典表生成带有样式的excel,通过kettle pentaho报表输出组件导出形成数据字典,最终形成的数据字典样式如下图: 案例适用范围: pentaho repor…

1. Prism系列之数据绑定

Prism系列之数据绑定 文章目录 Prism系列之数据绑定一、安装Prism二、实现数据绑定三、更换数据源 一、安装Prism 创建一个WPF工程,创建名为 PrismNewSample 的WPF项目。 使用管理解决方案的Nuget包 在上面或许我们有个疑问? 为啥安装prism会跟Pri…

java springboot+jsoup写一段爬虫脚本 将指定地址的 图片链接 文本 超链接地址存入自己的属性类对象中

首先 还是最基本的 要在 pom.xml 引入依赖 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.14.1</version> </dependency>然后 我们可以在项目中创建一个属性类 我这里就叫 WebContent了…

STM32使用SIM900A、SIM800C、SIM800A完成短信发送、连接onenet上传数据、拨打电话_完整教程

一、前言 本篇文章介绍SIM800C 、SIM800A、SIM900A 等等系列的模块的常用AT指令,讲解模块的使用方法,演示短信发送、拨打电话、网络连接,与服务器通信等常用案例。 如果只是用到发送短信、拨打电话、连接网络通信、这些模块的AT指令是兼容的。 文章最后贴了完整的STM32代码…

关于put_response和get_response的总结

Response总结&#xff0c;共三种情况 &#xff08;1&#xff09;每一笔都等response -> 直接get_response 注意put_response的前提是当前的seq的body没有直接结束&#xff0c;这个body一定是最底层发req的那个seq的body &#xff08;2&#xff09;连续发送数据&#xff0…

龙芯loongarch64安装numpy报错“No module named ‘numpy.core._multiarray_umath‘”

前言 在之前编译安装Python3.8的文章中说明了,龙芯仓库的很多包都有问题,安装之后很多无法使用,比如安装numpy后,就会出现“No module named numpy.core._multiarray_umath” 问题复现 配置pip源 vim /etc/pip.conf 复制下面的内容并保存 [global] timeout = 60 index-url…

电力行业的革新者:配网故障定位系统引领行业进步

随着科技的不断发展&#xff0c;电力行业也在不断地进行改革和创新。在这个过程中&#xff0c;恒峰智慧科技设计的配网故障定位系统作为一种先进的技术手段&#xff0c;正逐步引领行业的进步。本文将详细介绍配网行波型故障预警与定位系统的工作原理、功能特点以及在电力行业中…

easyrecovery14破解个人版数据恢复软件下载

easyrecovery14是easyrecovery系列软件的新版本&#xff0c;也是目前行业领先的数据恢复软件&#xff0c;具备更快捷、更高效、更便捷三大特色&#xff0c;能够帮助用户轻松恢复电脑丢失的数据。目前软件支持恢复不同存储介质数据&#xff0c;包括硬盘、光盘、U盘/移动硬盘、数…

C++笔记汇总(随时更新)

你好&#xff0c;这里是争做图书馆扫地僧的小白。 个人主页&#xff1a;争做图书馆扫地僧的小白_-CSDN博客 目标&#xff1a;希望通过学习技术&#xff0c;期待着改变世界。 目录 前言 一、C语言向C语言过度的知识点 二、C语言的相关知识 总结 前言 2023.12.13 之前撰写的笔…

ProcessOn在线绘制部分项目流程图

目录 一、ProcessOn 1.1 简介 1.2 官方网站 二、Axure自定义元件库 2.1 新建元件库 2.2 自定义元件 2.3 添加元件库 三、HIS系统门诊流程图 四、HIS系统住院流程图 五、HIS系统药品采购入库流程图 六、OA会议流程图 一、ProcessOn 1.1 简介 ProcessOn是一款在线的流…

后台业务管理系统原型模板,Axure后台组件库(整套后台管理页面)

后台业务系统需要产品经理超强的逻辑思维能力和业务理解能力&#xff0c;整理了一批后台原型组件及完整的用 Axure 8 制作的后台系统页面&#xff0c;方便产品经理们快速上手制作后台原型。 包括交互元件、首页、商品、订单、库存、用户、促销、运营、内容、统计、财务、设置、…

备忘录在手机哪里 这个方法轻松让轻松找到

作为一个常常忙于各种事务的人&#xff0c;我经常需要记录一些重要的事情&#xff0c;以免忘记。以前我总是使用纸质备忘录&#xff0c;但是随着科技的发展&#xff0c;我现在开始使用手机备忘录。然而&#xff0c;有时候我会找不到备忘录在哪里&#xff0c;让我感到非常困扰。…

1、初识 llvm源码编译 及virtualbox和ubuntu环境搭建

很久没更新了&#xff0c;最近准备研究逆向和加固&#xff0c;于是跟着看雪hanbing老师学习彻底搞懂ollvm&#xff0c;终于把所有流程跑通了&#xff0c;中间遇到了太多的坑&#xff0c;所以必须记录一下&#xff0c;能避免自己和帮助他人最好。 环境搭建太重要了&#xff0c;…

Github、Gitee优秀的开源项目分享

先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;❤️ ❤️ ❤️ 资源收集不易&#xff0c;如果喜欢可以关注我哦&#xff01; ​如果本篇内容对你有所启发&#xff0c;欢迎访问我的个人博客了解更多内容&#xff1a;链接地址 ​ Java 项目 javacore - Java …

差分数组详解,一维二维差分

文章目录 差分数组引言差分数组的定义二维差分数组二维差分数组代码实现 总结OJ练习 差分数组 引言 如果给你一个包含500个元素的数组&#xff0c;让你把从第一个元素到第100个元素的值都加上1&#xff0c;你会毫不犹豫的说枚举&#xff01;那么如果给你一个包含5000万个元素的…

03 python循环语句

3.1while循环基本语法 # 演示while循环的基础应用i0 while i<100 :print(不到100)i 1while循环基本案例 import random num random.randint(1, 100) count 0 while True:guess_num int(input(随机输入数字&#xff1a;))count 1if guess_num num :print(jie shu)br…

qiankun中主系统启动子系统本地静态图片加载404或者跨域问题

由于本地启动主系统和子系统&#xff0c;如果主系统内不放子系统的图片就会导致主系统访问不到子系统的图片 对于这个问题有三种解决方案&#xff0c;这里一一说明 1、第一种也是我常用的&#xff0c;就是把子系统中的静态图片全部转为base64这样通过主系统访问的时候就不是通…

为什么我的流量卡流量没有全部到账?是什么情况?

为什么我的流量卡流量没有全部到账&#xff1f;是什么情况&#xff1f; 网上的的流量套餐虽然便宜&#xff0c;但是有网友却反应&#xff0c;流量卡在激活之后出现“购买的套餐与实际流量不符合”的情况&#xff0c;这到底是什么原因呢&#xff1f; “流量卡和实际流量不符”&a…