SQL进阶 | 自连接

概述

        SQL的自连接是指在一个SQL表中,使用自身表格中的实例进行联接并查询的操作。自连接通常使用别名来标识一个表格,在自连接中,表格被视为两个不同的表格,并分别用不同的别名来标识。然后,在WHERE子句中使用这些别名,将它们连接起来,以创建一种与自身关联的视图。

组合

        假设这里有一张存放了商品名称及价格的表,表里有“苹果、橘子、香蕉”这 3 条记录。

针对不同的需求,有不同的组合结果:

排列A(n,k)

查询出所有的组合结果,有序集合。

select p1.name as name_1, p2.name as name_2
from products p1, products p2;

 

 组合C(n,k)

查询出所有的组合结果,有相同元素的只查出一条。无序集合。

select p1.name as name_1, p2.name as name_2from products p1, products p2where p1.name > p2.name;

 

        使用等号“=”以外的比较运算符,如“<、>、<>”进行的连接称为“非等值连接”。这里将非等值连接与自连接结合使用了,因此称为“非等值自连接”。

查找局部不一致的列

        还是这张商品表,要查找出价格相同,名称不同的组合。

 使用非等值连接实现。

 select distinct p1.name,p1.pricefrom products p1,products p2where p1.name <> p2.name and p1.price = p2.price

 

排序

        现在,我们要按照价格从高到低的顺序,对下面这张表里的商品进行排序。我们让价格相同的商品位次也一样,而紧接着它们的商品则有两种排序方法,一种是跳过之后的位次,另一种是不跳过之后的位次。

使用窗口函数实现。

select name,price,rank() over(order by price desc) as rank_1,dense_rank() over(order by price desc) as rank_2
from products;

        RANK函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。也就是说,如果有多个记录的分数相同,那么这些记录的排名将会一样,并且下一个排名将会跳过这些排名相同的记录。

        DENSE_RANK函数也返回一个唯一的值,但当碰到相同数据时,所有相同数据的排名都是一样的。与RANK函数不同的是,DENSE_RANK函数在下一个排名中会继续紧随这些排名相同的行,而不会跳过。也就是说,如果有多个记录的分数相同,那么这些记录的排名将会一样,并且下一个排名将会紧随在它们后面。

        总的来说,RANK和DENSE_RANK都是用于排名的函数,但它们的策略略有不同。RANK函数在遇到相同数据时会产生间断的排名,而DENSE_RANK函数则会产生连续的排名

 使用非等值自连接实现。

select p1.name,p1.price,( select count(p2.price) from products p2 where p2.price > p1.price ) + 1 as rank_1
from products p1
order by rank_1

         在子查询中,统计出价格比自己高的记录的条数并将其作为自己的位次,由于一定会存在价格最高的商品没有比自己高的记录,所以位次会从0开始统计,在子查询的结果中+1能更明显的展示出排名。

外连接和内连接

        外连接(Outer Join)可以分为左外连接(Left Outer Join)、右外连接(Right Outer Join)和全外连接(Full Outer Join)。左外连接返回包括左表中的所有记录和右表中连接字段相等的记录,右外连接返回包括右表中的所有记录和左表中连接字段相等的记录,全外连接返回左右表中所有的记录和左右表中连接字段相等的记录。

        内连接(Inner Join)是一种常见的连接方式,它只返回两个表中连接字段相等的行。内连接使用比较运算符根据每个表共有的列的值匹配两个表中的行。

        还是上面那个例子,使用外连接来实现。

select p1.name,max(p1.price) as price,count(p2.name) + 1 as rank_1
from products p1 left join products p2 on p1.price < p2.price
group by p1.name
order by rank_1

        通过左外连接,与价格大于自己的商品进行连接,按照商品名称p1进行分组,统计商品名称p2的记录条数,最终结果和上面相同。

        使用内连接实现。

select p1.name,max(p1.price) as price,count(p2.name) + 1 as rank_1
from products p1 inner join products p2 on p1.price < p2.price
group by p1.name
order by rank_1

 

        通过查询出的条件,可以发现,不存在排名为1的价格为100的橘子商品,这是因为内连接只会查找出p1.price < p2.price的记录,找不到比橘子价格还高的商品,它就被排除掉了。

总结

  • 自连接经常和非等值连接结合起来使用。
  • 自连接和 GROUP BY 结合使用可以生成递归集合。
  • 将自连接看作不同表之间的连接更容易理解。
  • 应把表看作行的集合,用面向集合的方法来思考。
  • 自连接的性能开销更大,应尽量给用于连接的列建立索引。

练习题 

1.请使用表products,求出两列可重组合。

代码如下: 

 select p1.name as name_1,p2.name as name_2 from products p1,products p2where p1.name <= p2.name

 

2. 这里准备了下面这样增加了“地区”列的新表 DistrictProducts,请计算一下各个地区商品价格的位次。

代码如下:

select d1.district,d1.name,d1.price,count(d2.name)+1 as rank_1
from districtproducts d1 left join districtproducts d2 on d1.price < d2.price and d1.district = d2.district
group by district,name,price
order by district,rank_1 

3.假设有下面这样一张表DistrictProducts2,里边原本就包含了“位次”列。不过,“位次”列的初始值都是 NULL。往这个列里写入位次。

代码如下:

update districtproducts2 p1
set ranking = (select rank_1 from(select count(p2.price) +1 rank_1from districtproducts2 p2where p1.district = p2.district and p2.price > p1.price) p3)

 

需要注意的是如果是下列代码,会报错。

 UPDATE DistrictProducts2 P1SET ranking = (SELECT COUNT(P2.price) + 1 FROM DistrictProducts2 P2WHERE P1.district = P2.districtAND P2.price > P1.price);

 报错信息:

意思是不能先select出同一表中的某些值,再update这个表(在同一语句中)。 所以使用一张临时表来解决问题。

扩展

        使用PARTITION BY子句

        PARTITION BY子句用于在窗口函数中对结果集进行分区,以便在每个分区中进行独立的计算。PARTITION BY子句通常与ORDER BY子句一起使用,以便将数据按照指定的列进行排序,并将排序后的数据划分为多个分区。

        PARTITION BY子句可以将数据按照指定的列进行分组,并在每个分区中进行独立的计算。它通常与窗口函数一起使用,以便在每个分区中计算聚合函数(如SUM、AVG、MAX等)的值。

UPDATE DistrictProducts2
SET ranking =(SELECT P1.rankingFROM (SELECT district , name ,RANK() OVER(PARTITION BY districtORDER BY price DESC) AS rankingFROM DistrictProducts2) P1WHERE P1.district = DistrictProducts2.districtAND P1.name = DistrictProducts2.name);

        PARTITION BY 子句将数据按照district进行分组,并在每个分区中按照price列进行降序排序,并结合RANK函数生成排名。

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

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

相关文章

【c】数组元素移动

本题的难点之处就是不让你创建新的数组&#xff0c;而且移动的距离也没有给限制&#xff0c;比如有7个数&#xff0c;本题没有限制必须移动距离小于7&#xff0c;也可能移动的距离大于7&#xff0c;甚至更多&#xff0c;下面附上我的代码 #include<stdio.h>int main() {…

ERA5逐时、逐日、逐月气象数据的手动下载与Python代码批量下载方法

本文介绍在ERA5气象数据的官方网站中&#xff0c;手动下载、Python代码自动批量下载逐小时、逐日与逐月的ERA5气象数据各类产品的快捷方法。 ERA5&#xff08;fifth generation ECMWF atmospheric reanalysis of the global climate&#xff09;是由欧洲中期天气预报中心&#…

千帆竞渡,鸿蒙已过万重山

近期&#xff0c;华为宣布其自主研发的鸿蒙Next系统将不再兼容Android系统&#xff0c;而是完全独立运营。 也就是说&#xff0c;你的 Android APK 已经不能在 HarmonyOS NEXT 上运行&#xff0c;因为系统已经不存在 AOSP 代码&#xff0c;甚至没有 JVM。 此举意味着鸿蒙系统…

SSD在AI发展中的关键作用:从高速缓存到数据湖-1

随着人工智能技术的飞速发展&#xff0c;存储在其中发挥着至关重要的作用。特别是在AI训练过程中&#xff0c;存储SSD&#xff08;固态硬盘&#xff09;的高性能和可靠性对于提升训练效率和保证数据安全具有不可替代的作用。 存储SSD在AI发展中的作用和趋势&#xff0c;存储将…

css的介绍与实战(有实现案例)

目录 css的简单介绍 css的基础选择器 css的字体属性&#xff08;背下来&#xff09; css的文本属性&#xff08;背下来&#xff09; css的引入方式&#xff08;背下来&#xff09; 实战案例 css的简单介绍 HTML 的局限性 说起 HTML&#xff0c;这其实是个非常单纯的家伙…

mmyolo的bbox_loss和检测bbox都是空

最近用mmyolo训练自己的数据集的时候发现训练的时候loss_bbox0&#xff0c;测试和eval的时候结果也全是空的&#xff0c;排除了数据集读取的问题&#xff0c;最后发现是config中自定义了自己的类别但是没有传给dataset。。。 简而言之&#xff0c;在自定义了数据集里的metainf…

【语义分割数据集】——imagenet语义分割

地址&#xff1a;https://github.com/LUSSeg/ImageNet-S 1 例图 2. 类别和数量信息 疑问 根据原文的描述&#xff1a;Based on the ImageNet dataset, we propose the ImageNet-S dataset with 1.2 million training images and 50k high-quality semantic segmentation annot…

微服务网关组件Gateway实战

1. 需求背景 在微服务架构中&#xff0c;通常一个系统会被拆分为多个微服务&#xff0c;面对这么多微服务客户端应该如何去调用呢&#xff1f;如果根据每个微服务的地址发起调用&#xff0c;存在如下问题&#xff1a; 客户端多次请求不同的微服务&#xff0c;会增加客户端代码…

Python数值类型(整形、浮点型和复数)及其用法

数值类型是计算机程序最常用的一种类型&#xff0c;既可用于记录各种游戏的分数、游戏角色的生命值、伤害值等&#xff0c;也可记录各种物品的价格、数量等&#xff0c;Python 提供了对各种数值类型的支持&#xff0c;如支持整型、浮点型和复数。 Python整型 Python 3 的整型…

二手车选购参考:杜卡迪Monster 欧系街车的代表,Ducati的销冠。

哈喽大家好&#xff0c;有几天没给大家更新二手车系列了&#xff0c;主要是一时之间想不到特别好的车型&#xff0c;因为预算的关系&#xff0c;所以我们这个栏目的售价将会卡在4~5万元左右&#xff0c;是国内绝大多数人努力都可以够得着的价格&#xff0c;也是国产中大排的新车…

排程系统中关于任务优先级的需求延伸与设计构思

无论是面向销售订单的MPS&#xff0c;还是基于多工序制约关系的APS&#xff0c;还是具体车间生产中针对单一工序的任务作业调度优化&#xff0c;都存在基于被排程对象(例如销售订单、生产工单、工序任务)的优先级进行优化的需求场景。当我们仅在宏观、较高层次的角度考虑&#…

UDP报文格式详解

✏️✏️✏️各位看官好&#xff0c;今天给大家分享的是 传输层的另外一个重点协议——UDP。 清风的CSDN博客 &#x1f6e9;️&#x1f6e9;️&#x1f6e9;️希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&#xff0…