【postgresql 基础入门】自然连接(natural join)与交叉连接(cross join),等价SQL变换形式,以及它们独到的应用场景

这篇具有很好参考价值的文章主要介绍了【postgresql 基础入门】自然连接(natural join)与交叉连接(cross join),等价SQL变换形式,以及它们独到的应用场景。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

自然连接与交叉连接

专栏内容

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

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

一、前言


本文重点介绍natural join与cross join的用法,以及它们的应用场景。

二、概述


与前面介绍的left join, right join, inner join不同,本文介绍两种新的join方式,它们不需指定连接的列。

  • 自然连接natural join,在两个表上的名称相同的列上进行连接;
  • 交叉连接cross join,在两个表上的所有列进行连接,即表1的所有行与表2的所有行进行一次连接;

下面一起来看看它们的用法,以及分别用于那些场景中。

三、自然连接


自然连接的语法

自然连接natural join的基本语法结构如下:

SELECT select_target_list
FROM tablename1 NATURAL [INNER, LEFT, RIGHT] JOIN tablename2;

在natural join时,还可以指定连接的方式inner, left, right,如果不指定时,默认为inner方式。

等价的join写法,类似于以下语法格式:

SELECT select_target_list
FROM tablename1 [INNER, LEFT, RIGHT] JOIN tablename2 
ON tablename1.column_name1 = tablename2.column_name2;

下面通过案例演示来体会。

案例演示

作为演示的准备,首先创建两张表,并插入数据。

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);
  • natural inner join

自然连接的inner查询,两表中都有列名customer_id,它作为关联列。

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

可以看到结果是两表的内联接。

当然查询SQL可以写作以下形式,结果也是相同的。

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

还有它的等价形式,如下:

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.00
           1 | John Doe    | john@example.com |        2 |           1 | 2023-02-01 |       200.00
           2 | Jane Smith  | jane@example.com |        3 |           2 | 2023-02-15 |       150.00
           3 | Bob Johnson | bob@example.com  |        4 |           3 | 2023-03-01 |        75.00
(4 rows)

以上几种SQL写法查出来的结果都是一样的,它都是以内联的方式来得到结果。

  • natural left/right join

其它的left,right连接也是类似的,与对应的left,right join有相同的效果。


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

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

当然也可以转换为对应的指定联接列的 join语句,这里不再赘述。

注意事项

在使用自然连接时,需要特别注意,因为它没有指定关联的列,SQL写法更加简洁,但是这也埋下了一个大坑,来看下面的两张表。

CREATE TABLE customers1 (
  customer_id INT PRIMARY KEY,
  name VARCHAR(50),
  email VARCHAR(50),
  ctime timestamp default now()
);

CREATE TABLE orders1 (
  order_id INT PRIMARY KEY,
  customer_id INT,
  order_date DATE,
  total_amount DECIMAL(10,2),
  ctime timestamp  default now()
);

在customers1与orders1表中,分别增加了一列ctime来记录创建的时间,两列的名称一样,此时两张表中有两列的名称相同。

然后上面的数据更换表名后插入,再次执行自然连接。

postgres=# select * from customers1 ;
 customer_id |    name     |       email        |           ctime
-------------+-------------+--------------------+----------------------------
           1 | John Doe    | john@example.com   | 2024-03-26 08:13:37.416833
           2 | Jane Smith  | jane@example.com   | 2024-03-26 08:13:37.416833
           3 | Bob Johnson | bob@example.com    | 2024-03-26 08:13:37.416833
           4 | Steven John | steven@example.com | 2024-03-26 08:13:37.416833
           5 | Kenidy      | Kenidy@example.com | 2024-03-26 08:13:37.416833
(5 rows)

postgres=# select * from orders1;
 order_id | customer_id | order_date | total_amount |           ctime
----------+-------------+------------+--------------+----------------------------
        1 |           1 | 2023-01-01 |       100.00 | 2024-03-26 08:13:54.054266
        2 |           1 | 2023-02-01 |       200.00 | 2024-03-26 08:13:54.054266
        3 |           2 | 2023-02-15 |       150.00 | 2024-03-26 08:13:54.054266
        4 |           3 | 2023-03-01 |        75.00 | 2024-03-26 08:13:54.054266
(4 rows)

数据与上例一致,只是多了创建本条数据的时间。

postgres=# select * from customers1 natural inner join orders1;
 customer_id | ctime | name | email | order_id | order_date | total_amount
-------------+-------+------+-------+----------+------------+--------------
(0 rows)

居然没有查到数据,这是因为连接时使用了ctime作为联接列导致,所以大家在使用时一定要注意,表中是否有多余的相同名称和类型的列存在。

四、交叉连接


交叉连接,也就是我们常说的笛卡尔积,表1的所有行与表2的每一行行进行联接,结果数据行数为两表行数的积。

下面我们通过语法格式,案例演示,应用场景三个部分来详细介绍交叉连接。

cross join语法

SELECT 
  select_target_list 
FROM tablename1 CROSS JOIN tablename2;

在交叉连接中,不用指定inner,left,right,其实它不需要有联接列,而是将两表的两行数据直接拼接起来组成结果集中的新行。

等价的SQL写法如下:

SELECT 
  select_target_list 
FROM tablename1, tablename2;

案例演示

演示的表和数据仍然使用上例中的customers与orders表。

cross join的写法的SQL执行结果如下:

postgres=# select * from customers cross join orders ;
 customer_id |    name     |       email        | order_id | customer_id | order_date | total_amount
-------------+-------------+--------------------+----------+-------------+------------+--------------
           1 | John Doe    | john@example.com   |        1 |           1 | 2023-01-01 |       100.00
           2 | Jane Smith  | jane@example.com   |        1 |           1 | 2023-01-01 |       100.00
           3 | Bob Johnson | bob@example.com    |        1 |           1 | 2023-01-01 |       100.00
           4 | Steven John | steven@example.com |        1 |           1 | 2023-01-01 |       100.00
           5 | Kenidy      | Kenidy@example.com |        1 |           1 | 2023-01-01 |       100.00
           1 | John Doe    | john@example.com   |        2 |           1 | 2023-02-01 |       200.00
           2 | Jane Smith  | jane@example.com   |        2 |           1 | 2023-02-01 |       200.00
           3 | Bob Johnson | bob@example.com    |        2 |           1 | 2023-02-01 |       200.00
           4 | Steven John | steven@example.com |        2 |           1 | 2023-02-01 |       200.00
           5 | Kenidy      | Kenidy@example.com |        2 |           1 | 2023-02-01 |       200.00
           1 | John Doe    | john@example.com   |        3 |           2 | 2023-02-15 |       150.00
           2 | Jane Smith  | jane@example.com   |        3 |           2 | 2023-02-15 |       150.00
           3 | Bob Johnson | bob@example.com    |        3 |           2 | 2023-02-15 |       150.00
           4 | Steven John | steven@example.com |        3 |           2 | 2023-02-15 |       150.00
           5 | Kenidy      | Kenidy@example.com |        3 |           2 | 2023-02-15 |       150.00
           1 | John Doe    | john@example.com   |        4 |           3 | 2023-03-01 |        75.00
           2 | Jane Smith  | jane@example.com   |        4 |           3 | 2023-03-01 |        75.00
           3 | Bob Johnson | bob@example.com    |        4 |           3 | 2023-03-01 |        75.00
           4 | Steven John | steven@example.com |        4 |           3 | 2023-03-01 |        75.00
           5 | Kenidy      | Kenidy@example.com |        4 |           3 | 2023-03-01 |        75.00
(20 rows)

可以看到结果集总共有20行数据,是两表的行数积,同时结果集中的列是两表所有列的拼接。

它的等价写法SQL的执行结果如下:

postgres=# select * from customers , orders ;
 customer_id |    name     |       email        | order_id | customer_id | order_date | total_amount
-------------+-------------+--------------------+----------+-------------+------------+--------------
           1 | John Doe    | john@example.com   |        1 |           1 | 2023-01-01 |       100.00
           2 | Jane Smith  | jane@example.com   |        1 |           1 | 2023-01-01 |       100.00
           3 | Bob Johnson | bob@example.com    |        1 |           1 | 2023-01-01 |       100.00
           4 | Steven John | steven@example.com |        1 |           1 | 2023-01-01 |       100.00
           5 | Kenidy      | Kenidy@example.com |        1 |           1 | 2023-01-01 |       100.00
           1 | John Doe    | john@example.com   |        2 |           1 | 2023-02-01 |       200.00
           2 | Jane Smith  | jane@example.com   |        2 |           1 | 2023-02-01 |       200.00
           3 | Bob Johnson | bob@example.com    |        2 |           1 | 2023-02-01 |       200.00
           4 | Steven John | steven@example.com |        2 |           1 | 2023-02-01 |       200.00
           5 | Kenidy      | Kenidy@example.com |        2 |           1 | 2023-02-01 |       200.00
           1 | John Doe    | john@example.com   |        3 |           2 | 2023-02-15 |       150.00
           2 | Jane Smith  | jane@example.com   |        3 |           2 | 2023-02-15 |       150.00
           3 | Bob Johnson | bob@example.com    |        3 |           2 | 2023-02-15 |       150.00
           4 | Steven John | steven@example.com |        3 |           2 | 2023-02-15 |       150.00
           5 | Kenidy      | Kenidy@example.com |        3 |           2 | 2023-02-15 |       150.00
           1 | John Doe    | john@example.com   |        4 |           3 | 2023-03-01 |        75.00
           2 | Jane Smith  | jane@example.com   |        4 |           3 | 2023-03-01 |        75.00
           3 | Bob Johnson | bob@example.com    |        4 |           3 | 2023-03-01 |        75.00
           4 | Steven John | steven@example.com |        4 |           3 | 2023-03-01 |        75.00
           5 | Kenidy      | Kenidy@example.com |        4 |           3 | 2023-03-01 |        75.00
(20 rows)

结果是相同的。

当然还有一种等价用法,利用inner join的条件表达式恒为true的方式,也可以达到cross join的效果。

postgres=# select * from customers inner join  orders on true;
 customer_id |    name     |       email        | order_id | customer_id | order_date | total_amount
-------------+-------------+--------------------+----------+-------------+------------+--------------
           1 | John Doe    | john@example.com   |        1 |           1 | 2023-01-01 |       100.00
           2 | Jane Smith  | jane@example.com   |        1 |           1 | 2023-01-01 |       100.00
           3 | Bob Johnson | bob@example.com    |        1 |           1 | 2023-01-01 |       100.00
           4 | Steven John | steven@example.com |        1 |           1 | 2023-01-01 |       100.00
           5 | Kenidy      | Kenidy@example.com |        1 |           1 | 2023-01-01 |       100.00
           1 | John Doe    | john@example.com   |        2 |           1 | 2023-02-01 |       200.00
           2 | Jane Smith  | jane@example.com   |        2 |           1 | 2023-02-01 |       200.00
           3 | Bob Johnson | bob@example.com    |        2 |           1 | 2023-02-01 |       200.00
           4 | Steven John | steven@example.com |        2 |           1 | 2023-02-01 |       200.00
           5 | Kenidy      | Kenidy@example.com |        2 |           1 | 2023-02-01 |       200.00
           1 | John Doe    | john@example.com   |        3 |           2 | 2023-02-15 |       150.00
           2 | Jane Smith  | jane@example.com   |        3 |           2 | 2023-02-15 |       150.00
           3 | Bob Johnson | bob@example.com    |        3 |           2 | 2023-02-15 |       150.00
           4 | Steven John | steven@example.com |        3 |           2 | 2023-02-15 |       150.00
           5 | Kenidy      | Kenidy@example.com |        3 |           2 | 2023-02-15 |       150.00
           1 | John Doe    | john@example.com   |        4 |           3 | 2023-03-01 |        75.00
           2 | Jane Smith  | jane@example.com   |        4 |           3 | 2023-03-01 |        75.00
           3 | Bob Johnson | bob@example.com    |        4 |           3 | 2023-03-01 |        75.00
           4 | Steven John | steven@example.com |        4 |           3 | 2023-03-01 |        75.00
           5 | Kenidy      | Kenidy@example.com |        4 |           3 | 2023-03-01 |        75.00
(20 rows)

应用场景

cross join来作两表的笛卡尔积,在一些场景下是非常有帮助的。

  • 遍历尝试

比如任务分配,那种任务与人员组合更合适,可能需要一一对应分析一下;还有一些计算推理,用到了枚举的方式,那就对所有可能结果都需要分析;

此时分析任务的输入或者驱动就是cross join的结果集。

  • 统计分析

假如要对所有门店与所有商品进行统计分析,看门店销售的情况,那么也需要作一个cross join,即使某个商品在该门店没有销售订单,也要有分析结果。

五、总结


本文分享了natural join和cross join的语法格式,同时它们有几种等价的SQL写法;因为natural join简洁的写法,有时会带来麻烦,在使用前要检查两表中是否有多列会产生join效果。

cross join虽然简单,但是它也有很多应用场景,在统计分析,任务分析等方面经常使用。

六、结尾


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

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

注:未经同意,不得转载!文章来源地址https://www.toymoban.com/news/detail-850408.html

到了这里,关于【postgresql 基础入门】自然连接(natural join)与交叉连接(cross join),等价SQL变换形式,以及它们独到的应用场景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 理解交叉熵(Cross Entropy)

    在 线性回归问题 中,常常使用MSE(Mean Squared Error)作为loss函数 而在 分类问题 中常常使用交叉熵作为loss函数。 在搜索“ 交叉熵 ”这个概念后,看到需要了解一些其他的名词。 衡量信息量的大小就是看这个信息消除不确定性的程度。 在一些比较确定的事情上,信息量就为0

    2024年02月05日
    浏览(29)
  • 交叉熵(Cross Entropy)损失函数

    交叉熵(Cross Entropy)损失函数是一种常用的损失函数,广泛应用于分类问题中,尤其是二分类问题和多分类问题。 假设有 N N N 个样本,每个样本有 C C C 个类别, y i ∈ { 0 , 1 } C y_i in {0,1}^C y i ​ ∈ { 0 , 1 } C 表示第 i i i 个样本的真实标签(one-hot编码), y i ^ ∈ [ 0 , 1 ]

    2024年02月09日
    浏览(31)
  • 深度学习:交叉验证(Cross Validation)

    首先,交叉验证的目的是为了让被评估的模型达到最优的泛化性能,找到使得模型泛化性能最优的超参值。在全部训练集上重新训练模型,并使用独立测试集对模型性能做出最终评价。 目前在一些论文里倒是没有特别强调这样的操作,很多研究使用的都是第一种:简单交叉验

    2024年02月02日
    浏览(30)
  • SQL入门之第十讲——INNER JOIN 内连接

    在实际的业务当中,往往需要多张表连接查询,这就会涉及到JOIN 连接 1. JOIN 连接的类型 INNER JOIN :内连接, 可以只写JOIN ,只有连接的两个表中,都存在连接标准的数据才会保留下来,相当于两个表的交集。如果前后连接的是同一个表,也叫自连接。 LEFT JOIN :左连接,也叫左

    2024年02月02日
    浏览(39)
  • 损失函数——交叉熵损失(Cross-entropy loss)

    交叉熵损失(Cross-entropy loss) 是深度学习中常用的一种损失函数,通常用于分类问题。它衡量了模型预测结果与实际结果之间的差距,是优化模型参数的关键指标之一。以下是交叉熵损失的详细介绍。 假设我们有一个分类问题,需要将输入数据x分为C个不同的类别。对于每个

    2024年02月02日
    浏览(37)
  • 自然语言处理(Natural Language Processing,NLP)

    自然语言处理(Natural Language Processing,NLP)是人工智能领域的一个重要分支,旨在使计算机能够理解、处理和生成人类自然语言。NLP 的目标是让计算机能够像人类一样有效地理解和交流,从而实现更自然、更智能的人机交互。 NLP的理解概括: 文本理解和分析: NLP技术能够从文

    2024年02月14日
    浏览(31)
  • Natural Language Processing自然语言处理(NLP)

       欢迎来到此处,这里是我边学*边 整理 的有关机械学*/深度学*的相关笔记。先前我对这方面的知识不是很了解,笔记整理必然有不妥之处,请见谅并斧正。 目录: 1.Word Vectors(词向量) 2.Neural Classifiers(神经分类器) 3.神经网络和反向传播 4.Dependency Parsing 5.语言模型(LM)和循环神经

    2024年02月08日
    浏览(33)
  • 自然语言处理(Natural Language Processing,NLP)解密

    专栏集锦,大佬们可以收藏以备不时之需: Spring Cloud 专栏: Python 专栏: Redis 专栏: TensorFlow 专栏: Logback 专栏: 量子计算: 量子计算 | 解密著名量子算法Shor算法和Grover算法 AI机器学习实战: AI机器学习实战 | 使用 Python 和 scikit-learn 库进行情感分析 AI机器学习 | 基于lib

    2024年01月21日
    浏览(38)
  • 自然语言处理技术(Natural Language Processing)知识点

    对自然语言处理相关的知识点进行总结。 自然语言处理(NLP)是一种人工智能技术,用于处理和理解自然语言文本。NLP 的目标是使计算机能够像人类一样理解、处理或生成自然语言,以便能够完成各种任务,例如文本分类、情感分析、机器翻译、问答系统等。 NLP 的实现通常

    2024年04月25日
    浏览(39)
  • 深度学习6:自然语言处理-Natural language processing | NLP

    目录 NLP 为什么重要? 什么是自然语言处理 – NLP NLP 的2大核心任务 自然语言理解 – NLU|NLI 自然语言生成 – NLG NLP(自然语言处理) 的5个难点 NLP 的4个典型应用 NLP 的 2 种途径、3 个核心步骤 总结 自然语言处理 “语言理解是人工智能领域皇冠上的明珠” 比尔·盖茨 在人工智能

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包