SQL 外连接

ops/2024/11/14 19:06:51/

 1 外连接

外连接是一种用于结合两个或多个表的方式,返回至少一个表中的所有记录。

左外连接

LEFT JOIN,左表为驱动表,右表为从表。返回驱动表的所有记录以及从表中的匹配记录。如果从表没有匹配,则结果中从表的部分为NULL。

右外连接

RIGHT JOIN,右表为驱动表,左表为从表。

全外连接

返回左右表中的所有记录,如果某侧表没有匹配,另一侧的结果为NULL。

表 外连接的三种类型

1.1 实践

1.1.1 行->列的转换:制作交叉表

图 课程信息t_courses表及期望输出

需求:O表示已学过,NULL表示尚未学习,利用课程表生成上面的交叉表。

-- 左连接
SELECT c1.name,
CASE WHEN c2.`name` IS NULL THEN NULL ELSE 'O' END AS 'SQL入门',
CASE WHEN c3.`name` IS NULL THEN NULL ELSE 'O' END AS 'UNIX基础',
CASE WHEN c4.`name` IS NULL THEN NULL ELSE 'O' END AS 'Java中级'
FROM (SELECT DISTINCT `name` FROM t_courses) c1
LEFT JOIN (SELECT `name` FROM t_courses WHERE course = 'SQL入门') c2 ON c1.name = c2.name 
LEFT JOIN (SELECT `name` FROM t_courses WHERE course = 'UNIX基础') c3 ON c1.name = c3.name 
LEFT JOIN (SELECT `name` FROM t_courses WHERE course = 'Java中级') c4 ON c1.name = c4.name 

上面代码比较直观和易于理解,但是大量用到了内嵌视图和连接操作,代码显得很臃肿。而且随着表头列数的增加,性能也会恶化。

一般情况下,外连接都可以用标量子查询替代。

-- 标量子查询
SELECT c.name,
(SELECT 'O' FROM t_courses WHERE `name` = c.name AND course = 'SQL入门') AS 'SQL入门',
(SELECT 'O' FROM t_courses WHERE `name` = c.name AND course = 'UNIX基础') AS 'UNIX基础',
(SELECT 'O' FROM t_courses WHERE `name` = c.name AND course = 'Java中级') AS 'Java中级'
FROM (SELECT DISTINCT `name` FROM t_courses) c; 

标量子查询(或者关联子查询),性能开销还是相当大的,因为其是针对SELECT返回的每一行来执行的。

-- 嵌套使用CASE表达式 
SELECT `name`,
CASE WHEN SUM(CASE WHEN course = 'SQL入门' THEN 1 ELSE 0 END) = 1 THEN 'O' else NULL END AS 'SQL入门',
CASE WHEN SUM(CASE WHEN course = 'UNIX基础' THEN 1 ELSE 0 END) = 1 THEN 'O' else NULL END AS 'UNIX基础',
CASE WHEN SUM(CASE WHEN course = 'Java中级' THEN 1 ELSE 0 END) = 1 THEN 'O' else NULL END AS 'Java中级'
FROM t_courses 
GROUP BY `name`;

1.1.2 列 -> 行的转换:汇总重复项于一列

图 员工个人信息t_personnel表及期望输出

-- 将列数据转换成行数据,使用UNION
SELECT employee,child_1 as child
FROM t_personnel
UNION
SELECT employee,child_2
FROM t_personnel
UNION
SELECT employee,child_3
FROM t_personnel;

表 使用UNION后的效果

但是像“铃木 NULL、工藤 NULL”这样的数据不希望输出,而”宫田 NULL”这样的数据要输出(他名下没有孩子,但是输出报表的时候,不能丢失这个员工信息)。

-- LEFT JOIN ... ON ...IN... 
SELECT p.employee,c.child
FROM t_personnel p
left join (SELECT *FROM (SELECT child_1 AS childFROM t_personnelUNION SELECT child_2 AS childFROM t_personnelUNIONSELECT child_3 AS childFROM t_personnel) tempWHERE child IS NOT NULL
) c ON c.child IN (p.child_1,p.child_2,p.child_3);

这样用了左连接,同时连接条件用了“IN”。

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

图 年龄段t_age_class、性别类别t_sex、人口t_population表及期望输出

SELECT a.age_range,s.sex,p.area1 AS '东北',p.area2 AS '关东'
FROM 
(
SELECT age_class,sex_cd,
SUM(CASE WHEN area IN ('秋田','青森') THEN population ELSE NULL END) AS area1,
SUM(CASE WHEN area IN ('东京','千叶') THEN population ELSE NULL END) AS area2
FROM t_population
GROUP BY age_class,sex_cd
) p 
RIGHT JOIN t_age_class a ON a.age_class = p.age_class
RIGHT JOIN t_sex s ON s.sex_cd = p.sex_cd;

上面代码会导致31岁~40岁这个年龄段丢失。

图 输出结果

应当将t_age_class 与 t_sex 先进行连接。

SELECT a.age_range,s.sex,
SUM(CASE WHEN p.area IN ('秋田','青森') THEN p.population ELSE NULL END) AS '东北',
SUM(CASE WHEN p.area IN ('东京','千叶') THEN p.population ELSE NULL END) AS '关东'
FROM t_age_class a 
CROSS JOIN t_sex s
LEFT JOIN t_population p ON p.age_class = a.age_class AND p.sex_cd = s.sex_cd
GROUP BY a.age_class,s.sex;

1.1.4 作为乘法运算的连接

图 商品信息t_items、商品销量信息t_sales_history表及期望输出

SELECT i.item_no,SUM(quantity) AS quantity
FROM t_items i 
LEFT JOIN t_sales_history s ON s.item_no = i.item_no
GROUP BY i.item_no;

1.1.5 将两张表汇总到一张表

图 两张待融合的表

需求:将t_table_2 的数据全部融合到t_table_1,要求,id相同,则对t_table_1进行更新,否则进行插入。

图 融合后的t_table_1表

-- t_table_1 的主键为id
INSERT INTO t_table_1(id,`name`) 
SELECT id,`name`
FROM t_table_2
ON DUPLICATE KEY 
UPDATE `name` = VALUES(`name`);

http://www.ppmy.cn/ops/133650.html

相关文章

机器学习(1)线性回归

前言   线性回归算法是机器学习深度学习入门的必学的算法,其算法原理虽然简单,但是却蕴含着机器学习中的一些重要的基本思想。许多功能更为强大的非线性模型可在线性模型的基础上通过引入层级结构或高维映射而得。同时机器学习深度学习的核心思想就是优…

渗透测试之 -- Linux基础

声明 学习视频来自B站UP主 泷羽sec,如涉及侵泷羽sec权马上删除文章笔记的只是方便各位师傅学习知识,以下网站涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 一、Openssl 1、openssl passwd -1 123 openssl一个开源加密工具包,用于各种解密、加…

宝塔面板中使用Acme SSL.cn申请的免费HTTPS SSL证书安装步骤

目录 1. 申请SSL证书 2. 宝塔面板安装SSL证书 申请免费ssl证书的网站:AcmeSSL.cn - 一个提供免费HTTPS证书申请的ACME自动化工具网站-免费提供申请Lets Encrypt、ZeroSSL、Google Public CA等CA证书-ACME自动化管理工具。 1. 申请SSL证书 按照上述提到的注册登录、…

netcat工具安装和使用

netcat是一个功能强大的网络实用工具,可以从命令⾏跨⽹络读取和写⼊数据。 netcat是为Nmap项⽬编写的,是⽬前分散的Netcat版本系列的经典。 它旨在成为可靠的后端⼯具,可⽴即为其他应⽤程序和⽤户提供⽹络连接。 一,下载安装 1&a…

《实时流计算系统设计与实现》-Part 2-笔记

做不到实时 做不到实时的原因 实时计算很难。通过增量计算的方式来间接获得问题的(伪)实时结果,即使这些结果带有迟滞性和近似性,但只要能够带来尽可能最新的信息,那也是有价值的。 原因可分成3个方面: …

apk反编译修改教程系列-----apk应用反编译中AndroidManifest.xml详细代码释义解析 包含各种权限 代码含义

在反编译apk应用中。需要增加或者减少有些apk功能或者权限类的修改。其中大多都在于 AndroidManifest.xml文件中。了解AndroidManifest.xml其中每串代码代表的含义对修改apk有着至关重要的作用。 通过博文了解💝💝💝💝 1💝💝💝💝----AndroidManifest.xml中代…

力扣104 : 二叉树最大深度

补:二叉树的最大深度 描述: 给定一个二叉树 root ,返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 何解? 树一般常用递归:递到叶子节点开始倒着处理

【go从零单排】XML序列化和反序列化

🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在 Go 语言中,处理 XML 数据主要使用 encoding/xml 包。这个包提供了…