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.mzph.cn/news/213915.shtml

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

相关文章

oracle异常:ORA-03297:文件包含在请求的 RESIZE 值以外使用的数据

出现这个问题&#xff0c;主要是在对表空间扩容的时候&#xff0c;扩容的大小<实际数据文件大小 1、扩容的语句 alter database datafile D:\APP\ADMINISTRATOR\ORADATA\ORCL\USER.DBF resize 2G; 2、若何确定扩容大小是否比实际文件大 根据路径找到文件&#xff0c;查看…

二十、FreeRTOS之Tickless低功耗模式

本节需要掌握以下内容&#xff1a; 1&#xff0c;低功耗模式简介&#xff08;了解&#xff09; 2&#xff0c; Tickless模式详解&#xff08;熟悉&#xff09; 3&#xff0c; Tickless模式相关配置项&#xff08;掌握&#xff09; 4&#xff0c;Tickless低功耗模式实验&…

自定义异步任务管理器和线程

import com.lancoo.common.utils.Threads; import com.lancoo.common.utils.spring.SpringUtils;import java.util.TimerTask; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit;/*** 异步任务管理器* * author lancoo*/ public c…

操作系统大会 openEuler Summit 2023即将召开,亮点不容错过

【12月11日&#xff0c;北京】数字化、智能化浪潮正奔涌而来。操作系统作为数字基础设施的底座&#xff0c;已经成为推动产业数字化、智能化发展的核心力量&#xff0c;为数智未来提供无限可能。12月15-16日&#xff0c;以“崛起数字时代 引领数智未来”为主题的操作系统大会 &…

〖Python网络爬虫实战㊷〗- 极验滑块介绍(四)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;订阅本专栏前必读关于专栏〖Python网络爬虫实战〗转为付费专栏的订阅说明作者&#xff1…

【ArcGIS Pro微课1000例】0049:根据坐标快速定位(创建点位)的常见方法

文章目录 一、转到XY1. 闪烁位置2. 平移3. 标记位置二、定位1. 坐标定位2. 添加到图形3. 添加至要素类三、添加XY坐标四、创建点要素一、转到XY 举例:经纬度坐标:113.2583286东, 23.1492340北 。 1. 闪烁位置 输入坐标,点击闪烁位置工具,即可在对应的位置出现一个绿色闪烁…

SQL注入漏洞利用

预计更新SQL注入概述 1.1 SQL注入攻击概述 1.2 SQL注入漏洞分类 1.3 SQL注入攻击的危害 SQLMap介绍 2.1 SQLMap简介 2.2 SQLMap安装与配置 2.3 SQLMap基本用法 SQLMap进阶使用 3.1 SQLMap高级用法 3.2 SQLMap配置文件详解 3.3 SQLMap插件的使用 SQL注入漏洞检测 4.1 SQL注入…

shiro入门demo

搭建springboot项目&#xff0c;引入以下依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--单元测试--><depe…

集的增删操作

集是可以修改的&#xff0c;增加元素可以用add和update函数。删除可以用pop、discard、remove等函数。 1 增加集里的元素 add函数的参数视为一个整体插入到集里&#xff0c;而update函数传入的参数是把要传入的元素拆分&#xff0c;做为个体传入到集合中。 s set("hell…

.9.png的创建

1、创建.9.png 选中图片&#xff0c;右击&#xff0c;选择Create 9-Patch file&#xff0c;点击确定会生成一个xxx.9.png的图片 2、绘制拉伸区域 在图片的最外边界绘制拉伸区域&#xff0c;按住鼠标左键不放&#xff0c;绘制完成后保存就可以使用了。绘制结果示意如下&…

phpstudy小皮(PHP集成环境)下载及使用

下载 https://www.xp.cn/download.html直接官网下载即可&#xff0c;下载完解压是个.exe程序&#xff0c;直接点击安装就可以&#xff0c;它会自动在D盘目录为D:\phpstudy_pro 使用 phpMyAdmin是集成的数据库可视化&#xff0c;这里需要下载一下&#xff0c;在软件管理-》网站程…

OPPO怎么录屏?教程来了,让你成为录屏达人

“有人知道OPPO怎么录屏吗&#xff0c;前阵子刚买的OPPO手机&#xff0c;用起来感觉挺流畅的&#xff0c;功能也很齐全&#xff0c;最近因为工作原因&#xff0c;需要用到录屏功能&#xff0c;但是我不知道怎么打开&#xff0c;就想问问大伙&#xff0c;OPPO怎么录屏呀。” 在…

Redis分片集群一步一步全过程搭建

文章目录 Redis搭建分片集群1. 搭建的分片集群结构2.准备实例和配置&#xff08;1&#xff09;创建目录&#xff08;2&#xff09;创建配置文件&#xff08;3&#xff09;将这个文件拷贝到每个目录下&#xff08;4&#xff09;修改每个目录下的redis.conf&#xff0c;将其中的6…

Yocto 还是 Buildroot,构建自定义嵌入式系统时,您会选择哪一种?

假设您正在采用集成平板开发新一代大型智能微波炉。这个创意不错吧&#xff01;现在&#xff0c;您需要构建自定义操作系统&#xff0c;在保证不会烧焦食物&#xff08;更不要烧毁房屋哦&#xff09;的前提下&#xff0c;辅助管理各项事务。除此之外&#xff0c;您还需要创建一…

px? pt? dp? em?rem?vw?vh?ch?ex?这些单位你了解吗?

目录 前言 一、常见单位 1、px单位 2、dp单位 3、pt单位 4、百分比% 5、em单位 6、rem单位 7、vw和vh单位 8、ch、ex单位 二、如何换算 1、 pt和px换算 2、px和dp换算 3、em和px换算 4、rem和px换算 三、总结 前言 前端开发在日常设计中除了最常用的 px 以外&…

第二十八章 控制到 XML 模式的映射 - 流类到 XML 类型的映射

文章目录 第二十八章 控制到 XML 模式的映射 - 流类到 XML 类型的映射将集合属性映射到 XML 模式 第二十八章 控制到 XML 模式的映射 - 流类到 XML 类型的映射 如果类或属性基于流&#xff0c;则它将投影为 XML 类型&#xff0c;如下表所示&#xff1a; IRIS 流的 XML 类型 …

使用BeautifulSoup 4和Pillow合并网页图片到一个PDF:一种高效的方式来处理网页图像

背景 ​ 网页上的培训材料&#xff0c;内容全是PPT页面图片。直接通过浏览器打印&#xff0c;会存在只打印第一页&#xff0c;并且把浏览器上无效信息也打印出来情况。但目标是希望将页面图片全部打印为pdf形式。 实现方案 利用网页“另存为”&#xff0c;将页面内所有图片资…

官宣!「湾区之光群星演唱会」拉开2024新年音乐华丽序幕!

万众期待&#xff0c;群星荟萃&#xff01;青春宝安时尚湾区——湾区之光群星演唱会即将在2024年1月5日闪耀亮相深圳宝安。 华语歌坛巨星天后齐聚一堂&#xff0c;携手多位实力唱将&#xff0c;共同呈现一场无与伦比的演唱会盛宴&#xff01;在深情而又充满力量的歌声之中&…

Linux修复磁盘坏道,重新挂载硬盘

修复磁盘 挂载报错&#xff1a; [rootlocalhost ~]$ mount /dev/sdb /mnt/mydevmount: /dev/sdb is write-protected, mounting read-only mount: wrong fs type, bad option, bad superblock on /dev/sdb,missing codepage or helper program, or other errorIn some cases …

15、lambda表达式、右值引用、移动语义

前言 返回值后置 auto 函数名 (形参表) ->decltype(表达式) lambda表达式 lambda表达式的名称是一个表达式 (外观类似函数)&#xff0c;但本质绝非如此 语法规则 [捕获表] (参数表) 选项 -> 返回类型 { 函数体; }lambda表达式的本质 lambda表达式本质其实是一个类…