【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 操作的是查询结果,将多个结果集合并成一个结果集,然后在这个总结果集上再进行二次查询处理;
也就是我们数学中的集合的几种
而更加总结的话,就涉及到关系代数中对于集合的操作:
集合操作主要包括以下几种:
- 并集操作(Union):将两个集合合并成一个集合,包括所有属于两个集合的元素。
- 交集操作(Intersection):将两个集合的公共元素组成一个新的集合。
- 差集操作(Difference):从一个集合中去掉属于另一个集合的元素,剩下的元素组成一个新的集合。
- 对称差集操作(Symmetric Difference):将属于一个集合但不属于另一个集合的元素,以及属于另一个集合但不属于一个集合的元素组成一个新的集合。
- 笛卡尔积操作(Cartesian Product):将两个集合的所有可能有序对组成一个新的集合。
多表 join 连接操作
在PostgreSQL中,多表查询是通过使用连接(JOIN)和交叉连接(CROSS JOIN)等操作来实现的。
连接操作是指将两个或多个表按照指定的条件进行关联,以获得它们之间的关系数据。
下面我们举例来说明,首先创建两张表custom 和 order;
以下是一个使用PostgreSQL进行JOIN操作的案例:
假设我们有两个表:customers和orders。customers表包含客户的信息,而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;
这里有几个关键部分:
SELECT语句:用于指定要检索的列和表。UNION、UNION ALL、EXCEPT和INTERSECT:这些关键字用于指定要执行的联合操作类型。WHERE子句:可选的条件,用于筛选结果。
联合类型说明
UNION:返回两个查询结果的并集,但会删除重复的行。UNION ALL:返回两个查询结果的并集,包括重复的行。EXCEPT:返回第一个查询结果中存在但在第二个查询结果中不存在的行。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
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!
相关文章:
【postgresql 基础入门】多表联合查询 join与union 并,交,差等集合操作,两者的区别之处
多表数据联合查询 专栏内容: postgresql内核源码分析手写数据库toadb并发编程 开源贡献: toadb开源库 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤&#x…...
很可惜,pyinstaller不是万能的
近期活不算少,但是真正新的东西很少,基本都是做些相似的功能,所以有精力想想之前悬而未决的问题,比如前两天写的加快软件启动速度的探索,这几天又想起一个之前没有解决的问题,这个问题之前也在博客写过&…...
0/1背包问题
例题HDU-2602 Problem Description Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … The bone collector had a big bag wi…...
Redis入门到精通——00数据类型
1、String 1.1、介绍 String 是最基本的 key-value 结构,key 是唯一标识,value 是具体的值,value其实不仅是字符串, 也可以是数字(整数或浮点数),value 最多可以容纳的数据长度是 512M 1.2、…...
PADS9.5使用记录
目录 一、概述 二、PADS Logic IN4148二极管封装 SOD-123封装 SOD-323封装 SOD-523封装 2N3904 1AM 三极管封装 78L05 7533-1 一、概述 PADS Logic 原理图绘制PADS Layout PCB 封装设计PADS Router 布线 二、PADS Logic …...
Axios post请求出现500错误
笔者在编写前端form表单传后端数据的时候,出现了以下问题 一、问题场景 当我用axios发送post请求的时候,出现了500错误 笔者找了很长时间错误,代码没问题,后端接口也没问题,后来发现问题出在实体类上了 当前端post请…...
【Leetcode】171.Excel 表列序号
一、题目 1、题目描述 给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如: A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例1: 输入: columnTitle = "A" 输出: 1示例2: 输入: colu…...
2023湖南省赛游记/题解
省赛拖了大哥们的后腿,感觉随便补个正常一队水平的人,我们一队肯定能AK。只能说自己真的菜,全程帮不上什么忙,还负贡献,真的想笑 B 暴力sg #include <bits/stdc.h> #define ll long long #define ull unsigned…...
海信电视U8KL使用体验:参数卷,画质技术也独有!
每个家庭成员对电视都有不同需求,如何能做到兼顾?看似需求众口难调,其实一台海信电视就能满足所有啦。 海信电视的参数不仅是最卷的,同时画质技术还是国内独有的,能把这样一台优秀的电视搬回家,无论电影、…...
E. Mishap in Club
题目: 样例1: 输入 --输出 1 样例2: 输入 --- 输出 3 思路: 数学贪心模拟思路,由于不知道在俱乐部的人数和在外面的人数,又要尽可能少的人数,那么定义两个变量,一个是里面的人数 i…...
UE4 自带体积云应用
新建空关卡 点击该选项 全部点击一遍 拖进场景...
RTP/RTCP 协议讲解
文章目录 前言一、RTP 协议1、RTP 协议概述2、RTP 工作机制3、RTP 协议的报文结构4、wireshark 抓取 RTP 报文 二、RTCP 协议1、RTCP 协议概述2、RTCP 工作机制3、RTCP 数据报4、wireshark 抓取 RTCP 报文 三、RTSP 和 RTP 的关系四、易混淆概念1、RTP over UDP 和 RTP over RT…...
倒计时15天!百度世界2023抢先看
近日消息,在10月17日即将举办的百度世界2023上,百度创始人、董事长兼首席执行官李彦宏将带来主题演讲,“手把手教你做AI原生应用”。 增设社会报名,有机会获得精美伴手礼 目前,百度世界大会已经开放公众参会报名&…...
Redis 哈希(Hash)数据类型和命令(数据类型 二)
基本概念 Hash是一个键值对的集合,其中每个键都是唯一的。每个键都可以关联多个字段和值,这使得Hash非常适合存储对象或结构化数据。 常用命令 存储、获取、删除:hset、hget、hdel # 添加键为name值为lin hset student name lin # 获取 h…...
[Linux]线程互斥
[Linux]线程互斥 文章目录 [Linux]线程互斥线程并发访问问题线程互斥控制--加锁pthread_mutex_init函数pthread_mutex_destroy函数pthread_mutex_lock函数pthread_mutex_unlock函数锁相关函数使用示例使用锁的细节加锁解锁的实现原理 线程安全概念常见的线程不安全的情况常见的…...
leetcode-239-滑动窗口最大值
题意描述: 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例: 输入:nums [1,3,-1,…...
基于大语言模型的智能问答系统应该包含哪些环节?
一个完整的基于 LLM 的端到端问答系统,应该包括用户输入检验、问题分流、模型响应、回答质量评估、Prompt 迭代、回归测试,随着规模增大,围绕 Prompt 的版本管理、自动化测试和安全防护也是重要的话题,本篇文章就来探索下这个过程…...
【Cesium创造属于你的地球】相机系统
相机系统里面有setView,flyTo,lookAt,viewBoundingsphere这几种方法,以下是相关的使用方法,学起来!!! setView 该方法可以直接切换相机视口,从而不需要通过一个飞入的效…...
运维困局下确保系统稳定的可行性
业务高速发展背后的困局 随着业务的快速发展,运维体系也逐步的完善起来。业务的稳定性和服务质量也在监控、可用性等体系的相互环抱下健康地成长。所有的问题、故障及影响稳定性的因素都在可控、可收敛的范围内,一切都向着好的方向发展。 这一切的背后…...
springmvc中DispatcherServlet关键对象
以下代码为 spring boot 2.7.15 中自带的 spring 5.3.29 RequestMappingInfo 请求方法相关信息封装,对应的信息解析在 RequestMappingHandlerMapping 的 createRequestMappingInfo() 中实现。 对于 RequestMapping 赋值的相关信息进行解析 protected RequestMappi…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
Linux入门(十五)安装java安装tomcat安装dotnet安装mysql
安装java yum install java-17-openjdk-devel查找安装地址 update-alternatives --config java设置环境变量 vi /etc/profile #在文档后面追加 JAVA_HOME"通过查找安装地址命令显示的路径" #注意一定要加$PATH不然路径就只剩下新加的路径了,系统很多命…...
【QT控件】显示类控件
目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏:QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...
