当前位置: 首页 > news >正文

【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
如有错误或者疏漏欢迎指出,互相学习。

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

相关文章:

【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湖南省赛游记/题解

省赛拖了大哥们的后腿&#xff0c;感觉随便补个正常一队水平的人&#xff0c;我们一队肯定能AK。只能说自己真的菜&#xff0c;全程帮不上什么忙&#xff0c;还负贡献&#xff0c;真的想笑 B 暴力sg #include <bits/stdc.h> #define ll long long #define ull unsigned…...

海信电视U8KL使用体验:参数卷,画质技术也独有!

每个家庭成员对电视都有不同需求&#xff0c;如何能做到兼顾&#xff1f;看似需求众口难调&#xff0c;其实一台海信电视就能满足所有啦。 海信电视的参数不仅是最卷的&#xff0c;同时画质技术还是国内独有的&#xff0c;能把这样一台优秀的电视搬回家&#xff0c;无论电影、…...

E. Mishap in Club

题目&#xff1a; 样例1&#xff1a; 输入 --输出 1 样例2&#xff1a; 输入 --- 输出 3 思路&#xff1a; 数学贪心模拟思路&#xff0c;由于不知道在俱乐部的人数和在外面的人数&#xff0c;又要尽可能少的人数&#xff0c;那么定义两个变量&#xff0c;一个是里面的人数 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抢先看

近日消息&#xff0c;在10月17日即将举办的百度世界2023上&#xff0c;百度创始人、董事长兼首席执行官李彦宏将带来主题演讲&#xff0c;“手把手教你做AI原生应用”。 增设社会报名&#xff0c;有机会获得精美伴手礼 目前&#xff0c;百度世界大会已经开放公众参会报名&…...

Redis 哈希(Hash)数据类型和命令(数据类型 二)

基本概念 Hash是一个键值对的集合&#xff0c;其中每个键都是唯一的。每个键都可以关联多个字段和值&#xff0c;这使得Hash非常适合存储对象或结构化数据。 常用命令 存储、获取、删除&#xff1a;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-滑动窗口最大值

题意描述&#xff1a; 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例&#xff1a; 输入&#xff1a;nums [1,3,-1,…...

基于大语言模型的智能问答系统应该包含哪些环节?

一个完整的基于 LLM 的端到端问答系统&#xff0c;应该包括用户输入检验、问题分流、模型响应、回答质量评估、Prompt 迭代、回归测试&#xff0c;随着规模增大&#xff0c;围绕 Prompt 的版本管理、自动化测试和安全防护也是重要的话题&#xff0c;本篇文章就来探索下这个过程…...

【Cesium创造属于你的地球】相机系统

相机系统里面有setView&#xff0c;flyTo&#xff0c;lookAt&#xff0c;viewBoundingsphere这几种方法&#xff0c;以下是相关的使用方法&#xff0c;学起来&#xff01;&#xff01;&#xff01; setView 该方法可以直接切换相机视口&#xff0c;从而不需要通过一个飞入的效…...

运维困局下确保系统稳定的可行性

业务高速发展背后的困局 随着业务的快速发展&#xff0c;运维体系也逐步的完善起来。业务的稳定性和服务质量也在监控、可用性等体系的相互环抱下健康地成长。所有的问题、故障及影响稳定性的因素都在可控、可收敛的范围内&#xff0c;一切都向着好的方向发展。 这一切的背后…...

springmvc中DispatcherServlet关键对象

以下代码为 spring boot 2.7.15 中自带的 spring 5.3.29 RequestMappingInfo 请求方法相关信息封装&#xff0c;对应的信息解析在 RequestMappingHandlerMapping 的 createRequestMappingInfo() 中实现。 对于 RequestMapping 赋值的相关信息进行解析 protected RequestMappi…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...