【postgresql 基础入门】多表联合查询 join与union 并,交,差等集合操作,两者的区别之处

多表数据联合查询

专栏内容

  • postgresql内核源码分析
  • 手写数据库toadb
  • 并发编程

开源贡献

  • toadb开源库

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

系列文章

  • 入门准备
  • postgrersql基础架构
  • 快速使用
  • 初始化集群
  • 数据库服务管理
  • psql客户端使用
  • pgAdmin图形化客户端
  • 数据库的使用
  • 创建数据库
  • 数据库操作
  • 表的使用
  • 表的创建
  • 表的操作
  • 数据查询
  • 数据查询
  • 多表联合查询

文章目录

  • 多表数据联合查询
  • 系列文章
  • 前言
  • 概述
  • 原理介绍
  • 多表 join 连接操作
    • 1. 内连接(INNER JOIN)
    • 2. 左连接(LEFT JOIN)
    • 3. 右连接(RIGHT JOIN)
    • 4. 全连接(FULL JOIN)
  • 多表union 操作
    • 联合类型说明
    • 1. union
  • 2. union all
  • 3. except
  • 3. intersect
  • 总结
  • 结尾

前言

postgresql 数据库是一款通用的关系型数据,在开源数据库中能与商业数据媲美,在业界也越来越流行。

因为是开源数据库,不仅公开源码,还有很多使用案例,好用的插件,所以它的慢慢变成了数据库的先驱和标准,通过postgresql可以很好从使用到原理,彻底搞懂;

如果是学习编程,也可以学到丰富的编程知识,数据结构,编程技巧,它里面还有很多精妙的架构设计,分层思想,可以灵活定制的思想。

本专栏主要介绍postgresql 入门使用,数据库维护管理,通过这些使用来了解数据库原理,慢慢了解postgresql是什么样的数据库,能做那些事情,以及如何做好服务,最关键的是这些知识都是面试的必备项。

概述

我们在实际应用中查询数据,往往涉及到多表的数据,如何使用一条SQL就能得到结果呢?

本文就来分享一下,多表数据的查询方法,并举例说明它们使用的技巧;

原理介绍

多表数据的联合查询,在postgresql 中有两个基本方法:

  • join 连接操作;
  • union 联合子查询;

多表join连接,其实就是通过某个列作为纽带,将多个实际的表连接成一张大表,然后在大表上进行查询;

而union 与 join 完全不同, union 通过联合 多个子查询结果,也就是说union 操作的是查询结果,将多个结果集合并成一个结果集,然后在这个总结果集上再进行二次查询处理;
也就是我们数学中的集合的几种

而更加总结的话,就涉及到关系代数中对于集合的操作:
集合操作主要包括以下几种:

  1. 并集操作(Union):将两个集合合并成一个集合,包括所有属于两个集合的元素。
  2. 交集操作(Intersection):将两个集合的公共元素组成一个新的集合。
  3. 差集操作(Difference):从一个集合中去掉属于另一个集合的元素,剩下的元素组成一个新的集合。
  4. 对称差集操作(Symmetric Difference):将属于一个集合但不属于另一个集合的元素,以及属于另一个集合但不属于一个集合的元素组成一个新的集合。
  5. 笛卡尔积操作(Cartesian Product):将两个集合的所有可能有序对组成一个新的集合。

多表 join 连接操作

在PostgreSQL中,多表查询是通过使用连接(JOIN)和交叉连接(CROSS JOIN)等操作来实现的。

连接操作是指将两个或多个表按照指定的条件进行关联,以获得它们之间的关系数据。
下面我们举例来说明,首先创建两张表custom 和 order;

以下是一个使用PostgreSQL进行JOIN操作的案例:

假设我们有两个表:customersorderscustomers表包含客户的信息,而orders表包含订单的信息。这两个表通过一个共同的字段customer_id相关联。

首先,让我们创建这两个表并插入一些数据:

CREATE TABLE customers (customer_id INT PRIMARY KEY,name VARCHAR(50),email VARCHAR(50)
);CREATE TABLE orders (order_id INT PRIMARY KEY,customer_id INT,order_date DATE,total_amount DECIMAL(10,2)
);INSERT INTO customers (customer_id, name, email)
VALUES (1, 'John Doe', 'john@example.com'),(2, 'Jane Smith', 'jane@example.com'),(3, 'Bob Johnson', 'bob@example.com'),(4, 'Steven John', 'steven@example.com'),(5, 'Kenidy', 'Kenidy@example.com');INSERT INTO orders (order_id, customer_id, order_date, total_amount)
VALUES (1, 1, '2023-01-01', 100.00),(2, 1, '2023-02-01', 200.00),(3, 2, '2023-02-15', 150.00),(4, 3, '2023-03-01', 75.00);

1. 内连接(INNER JOIN)

将两个表中的行进行匹配,返回满足连接条件的行。语法如下:

postgres=# SELECT * FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id;customer_id |    name     |      email       | order_id | customer_id | order_date | total_amount
-------------+-------------+------------------+----------+-------------+------------+--------------1 | John Doe    | john@example.com |        1 |           1 | 2023-01-01 |       100.001 | John Doe    | john@example.com |        2 |           1 | 2023-02-01 |       200.002 | Jane Smith  | jane@example.com |        3 |           2 | 2023-02-15 |       150.003 | Bob Johnson | bob@example.com  |        4 |           3 | 2023-03-01 |        75.00
(4 rows)

这里特意用 * 查出结果集中的所有列,让我们可以清晰看到结果集的全貌,可以看到join后的结果集,是两表的所有列的合并;

对于内联连,只是列出了符合连接条件的行,大家想一想,还有什么写法可以达到这种效果 。

对于, 条件写到where子句中也可以,所以内联接与where条件是等价的;

postgres=# select * from customers,orders where customers.customer_id = orders.customer_id;customer_id |    name     |      email       | order_id | customer_id | order_date | total_amount
-------------+-------------+------------------+----------+-------------+------------+--------------1 | John Doe    | john@example.com |        1 |           1 | 2023-01-01 |       100.001 | John Doe    | john@example.com |        2 |           1 | 2023-02-01 |       200.002 | Jane Smith  | jane@example.com |        3 |           2 | 2023-02-15 |       150.003 | Bob Johnson | bob@example.com  |        4 |           3 | 2023-03-01 |        75.00
(4 rows)

2. 左连接(LEFT JOIN)

在内连接的基础上,将左侧表中的所有行都包含在结果集中,即使右侧表中没有匹配的行。语法如下:

postgres=# select * from customers left join orders on  customers.customer_id = orders.customer_id;customer_id |    name     |       email        | order_id | customer_id | order_date | total_amount
-------------+-------------+--------------------+----------+-------------+------------+--------------1 | John Doe    | john@example.com   |        1 |           1 | 2023-01-01 |       100.001 | John Doe    | john@example.com   |        2 |           1 | 2023-02-01 |       200.002 | Jane Smith  | jane@example.com   |        3 |           2 | 2023-02-15 |       150.003 | Bob Johnson | bob@example.com    |        4 |           3 | 2023-03-01 |        75.005 | Kenidy      | Kenidy@example.com |          |             |            |4 | Steven John | steven@example.com |          |             |            |
(6 rows)

左联接后的结果集,列也是两表的合并,而行数与之前不同,左边表列表出所有行,而右边的表只列出了符合条件的行,对于左表多出的行,右表以空代替;

3. 右连接(RIGHT JOIN)

在内连接的基础上,将右侧表中的所有行都包含在结果集中,即使左侧表中没有匹配的行。语法如下:

postgres=# select * from customers right join orders on  customers.customer_id = orders.customer_id;customer_id |    name     |      email       | order_id | customer_id | order_date | total_amount
-------------+-------------+------------------+----------+-------------+------------+--------------1 | John Doe    | john@example.com |        1 |           1 | 2023-01-01 |       100.001 | John Doe    | john@example.com |        2 |           1 | 2023-02-01 |       200.002 | Jane Smith  | jane@example.com |        3 |           2 | 2023-02-15 |       150.003 | Bob Johnson | bob@example.com  |        4 |           3 | 2023-03-01 |        75.00
(4 rows)

右联接与左联接类似,结果集的行包括右表的所有行,左表只有符合联接表条件行;

4. 全连接(FULL JOIN)

相当于在左连接和右连接的基础上,同时做左连接和右连接,并返回两侧表中所有满足条件的行。语法如下:

postgres=# select * from customers full join orders on  customers.customer_id = orders.customer_id;customer_id |    name     |       email        | order_id | customer_id | order_date | total_amount
-------------+-------------+--------------------+----------+-------------+------------+--------------1 | John Doe    | john@example.com   |        1 |           1 | 2023-01-01 |       100.001 | John Doe    | john@example.com   |        2 |           1 | 2023-02-01 |       200.002 | Jane Smith  | jane@example.com   |        3 |           2 | 2023-02-15 |       150.003 | Bob Johnson | bob@example.com    |        4 |           3 | 2023-03-01 |        75.005 | Kenidy      | Kenidy@example.com |          |             |            |4 | Steven John | steven@example.com |          |             |            |
(6 rows)

全联接就是包括左右两条的所有行,没有符合条件的行以空代替;

多表union 操作

PostgreSQL中的联合查询是一种将多个SELECT语句的结果组合成一个结果集的方法。它允许您从多个表或查询中获取数据,并根据指定的条件将它们组合在一起。

联合查询的基本语法如下:

SELECT column1, column2, ...
FROM table1
UNION/UNION ALL/EXCEPT/INTERSECT
SELECT column1, column2, ...
FROM table2
WHERE condition;

这里有几个关键部分:

  1. SELECT语句:用于指定要检索的列和表。
  2. UNIONUNION ALLEXCEPTINTERSECT:这些关键字用于指定要执行的联合操作类型。
  3. WHERE子句:可选的条件,用于筛选结果。

联合类型说明

  1. UNION:返回两个查询结果的并集,但会删除重复的行。
  2. UNION ALL:返回两个查询结果的并集,包括重复的行。
  3. EXCEPT:返回第一个查询结果中存在但在第二个查询结果中不存在的行。
  4. INTERSECT:返回两个查询结果中共有的行。

请注意,使用联合查询时,确保每个查询中选择的列数和列类型是一致的,否则可能会导致错误。

1. union

合并两个表的数据并删除重复行

postgres=# select  customer_id from customers union select customer_id from orders ;customer_id
-------------23541
(5 rows)

这将返回一个结果集,其中包含两个表中所有不重复的行;

两个select 子句中的列数和类型必须一致才行,这样两个结果集才能合并到一起。

2. union all

合并两个表的数据并保留重复行

如果我们希望保留两个表中的所有行,包括重复的行,那么可以使用 UNION ALL 运算符。

postgres=# select  customer_id from customers union all select customer_id from orders ;customer_id
-------------123451123
(9 rows)

这将返回一个结果集,其中包含两个表中所有的行,包括重复的行。
同时,如果想要对结果进行排序;

可以使用 ORDER BY 子句。例如:

postgres=# select  customer_id from customers union all select customer_id from orders order by customer_id asc;customer_id
-------------111223345
(9 rows)

当然也可以加where 等其它子句;

3. except

获得两个集合的差,也就是前者集合中包括,而不属于后者集合的行;

postgres=# select  customer_id from customers except select customer_id from orders ;customer_id
-------------54
(2 rows)

也就是查询还没有产生订单的客户ID列表;

3. intersect

INTERSECT运算符用于找出两个SELECT语句结果集的交集。它的语法如下:

postgres=# select  customer_id from customers intersect select customer_id from orders order by customer_id asc;customer_id
-------------123
(3 rows)

这个类似于inner join,找到有订单的客户id列表;

总结

相同之处是,它们都是对结果集进行操作;

但是有明显的区别,join是将多表进行联接,产生结果集,然后再通过where等条件在联接后的结果集上再过滤;
而union并不限于表与表之间,而是对不同查询结果集,再进行集合操作,而且对于最终结果的列有要求,必须参与的集合列数量和类型要相同;

结尾

非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

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

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

相关文章

数据结构与算法基础(青岛大学-王卓)(8)

哎呀呀,sorry艾瑞波地,这次真的断更一个月了,又发生了很多很多事情,秋风开始瑟瑟了,老父亲身体查出肿瘤了,有病请及时就医,愿每一个人都有一个健康的身体,God bless U and FAMILY. 直…

实用调试技巧

引言:一个完美的代码离不开程序员的调试,所谓三分编写七分调试,今天我们给大家介绍几种实用的调试技巧。 1️⃣Bug的由来: 原意是指,小虫子,昆虫等,而人们也通常将电脑程序中的一些隐藏的缺陷或…

ThreeJS - 封装一个GLB模型展示组件(TypeScript)

一、引言 最近基于Three.JS,使用class封装了一个GLB模型展示,支持TypeScript、支持不同框架使用,具有多种功能。 (下图展示一些基础的功能,可以自行扩展,比如光源等) 二、主要代码 本模块依赖…

聊聊常见的IO模型 BIO/NIO/AIO 、DIO、多路复用等IO模型

聊聊常见的IO模型 BIO/NIO/AIO/DIO、IO多路复用等IO模型 文章目录 一、前言1. 什么是IO模型2. 为什么需要IO模型 二、常见的IO模型1. 同步阻塞IO(Blocking IO,BIO)2. 同步非阻塞IO(Non-blocking IO,NIO)3.…

C++--位图和布隆过滤器

1.什么是位图 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。比如int 有32位,就可以存放0到31这32个数字在不在某个文件中。当然,其他类型也可以。 2.位…

数据结构-哈希表

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 4.数据结构-哈希表_喜欢吃animal milk的博客-CSDN博客 文章目录 目录 系列文章目录 文章目录 前言 一 . 什么是哈希表&a…

Linux- fg命令 bg命令

fg fg是Unix-like操作系统(如Linux和macOS)中的一个shell内建命令,用于将后台作业带到前台执行。这个命令常用于与bg(后台执行)命令和jobs(列出当前作业)命令一起,进行shell中的作业…

Linux系统之部署Linux命令大全搜索工具

Linux系统之部署Linux命令大全搜索工具 一、linux-command介绍二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍 三、安装httpd软件3.1 检查yum仓库3.2 安装httpd软件3.3 启动httpd服务3.4 查看httpd服务状态3.5 防火墙和selinux设置3.6 浏览器测试web服务 四、安装linux-com…

LabVIEW开发虚拟与现实融合的数字电子技术渐进式实验系统

LabVIEW开发虚拟与现实融合的数字电子技术渐进式实验系统 数字电子技术是所有电气专业的重要学科基础,具有很强的理论性和实践性。其实验是提高学生分析、设计和调试数字电路能力,培养学生解决实际问题的工程实践能力,激发学生创新意识&…

Echarts 教程一

Echarts 教程一 可视化大屏幕适配方案可视化大屏幕布局方案Echart 图表通用配置部分解决方案1. titile2. tooltip3. xAxis / yAxis 常用配置4. legend5. grid6. series7.color Echarts API 使用全局echarts对象echarts实例对象 可视化大屏幕适配方案 rem flexible.js 关于flex…

Elasticsearch:与多个 PDF 聊天 | LangChain Python 应用教程(免费 LLMs 和嵌入)

在本博客中,你将学习创建一个 LangChain 应用程序,以使用 ChatGPT API 和 Huggingface 语言模型与多个 PDF 文件聊天。 如上所示,我们在最最左边摄入 PDF 文件,并它们连成一起,并分为不同的 chunks。我们可以通过使用 …

QA 云计算实验问题汇总

Q Win11中VMware虚拟网卡有感叹号 2023-9-27一位同学的win11的两个VMware17的虚拟网卡都有感叹号 A 清除注册表 步骤1 关闭VMWare虚拟化软件 步骤2 使用CCleaner pro 清理注册表 步骤3 重启系统 步骤4 VMware虚拟网卡上的感叹号消失。 Q Win11上的VisualBox的网卡消失了…

DBA数据库运维-MySQL安装篇(glibc,源码)

1. MySQL数据库版本 版本说明社区版: MySQL Community Edition (GPL)1.可以看做是企业版的“广泛体验版(小白鼠版)",未经各个专有系统平台的压力和性能测试 2.基于GPL协议发布,可以随意下载使用 3.没有任何官方技术支持服务企业版:MySQL Enterpris…

JUC中的设计模式

文章目录 1. 终止模式之两阶段终止模式 1. 终止模式之两阶段终止模式 需求:用一个线程每两秒检测***状态,当不想检测时,用另一个线程将其停止 在一个线程 T1 中如何“优雅”终止线程 T2?这里的【优雅】指的是给 T2 一个料理后事…

解决AndroidStudio 2022.3.1版本 引入maven报错的问题

升级新版Android Studio 2022.3.1后发现引入maven报错: 1、报错的日志 ^ Unexpected tokens (use ‘;’ to separate expressions on the same line)。 2、解决问题 2.1 新版本的引入方式: repositories {maven { url uri("https://maven.aliy…

前端开发网站推荐

每个人都会遇见那么一个人,永远无法忘却,也永远不能拥有。 以下是一些可以用来查找和比较前端框架的推荐网站: JavaScript框架比较: 这些网站提供了对不同JavaScript框架和库的详细比较和评估。 JavaScripting: 提供了大量的JavaS…

【CSS 中 link 和@import 的区别】

<link> 和 import 都可以用于引入 CSS 文件&#xff0c;但是两者有以下区别&#xff1a; 加载时间&#xff1a;<link> 标签在页面加载时同时加载&#xff0c;而 import 是在页面加载后才开始加载。 兼容性&#xff1a;<link> 标签可以被所有的浏览器正确解释…

防火墙基础之H3C防火墙分支与分支之间双向地址转换

分支与分支之间双向地址转换 原理概述&#xff1a; 防火墙&#xff08;英语&#xff1a;Firewall&#xff09;技术是通过有机结合各类用于安全管理​与筛选的软件和硬件​设备&#xff0c;帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障&#xff0c;以保护用户资…

凉鞋的 Godot 笔记 102. 场景与节点的增删改查

在上一篇&#xff0c;我们完成了 Godot 引擎的 Hello World 输出&#xff0c;并且完成了第一个基本循环: 通过这次基本循环的完成&#xff0c;我们获得了一点点的 Godot 使用经验&#xff0c;这非常重要。 有实践经验后再去补充理论 和 先学习理论后去实践相比&#xff0c;前者…

5、【第一步】自定义模型集成

【第一步】自定义模型集成 简介自定义模型类配置文件模型测试简介 Qlib 的模型库包括 LightGBM、MLP、LSTM 等模型。这些模型都是预测模型的例子。除了 Qlib 提供的默认模型外,用户还可以将他们自己的自定义模型集成到 Qlib 中。 用户可以按照以下步骤集成他们自己的自定义模…