SQL进阶(二)自连接

自连接

一、简述

通常SQL 在不同的表间进行连接运算,如内连接、外连接、交叉连接等,但是也可以在相同的表进行自连接运算。

使用场景

  • 可重排列
  • 排列
  • 组合
  • 查重
  • 排序


二、使用场景示例

问题描述:

分别查询出指定表中可重排列、排列、组合的结果

数据表格:product

name(商品名称)price(价格)
苹果50
橘子100
香蕉80

统计结果:可重排列

name_1name_2
苹果苹果
苹果橘子
苹果香蕉
橘子苹果
橘子橘子
橘子香蕉
香蕉苹果
香蕉橘子
香蕉香蕉

分析

通过交叉连接生成笛卡尔积,就可以得到以上结果。因为是可重排序,结果行数为 32=9。

SELECT p1.name AS name_1, p2.name AS name_2
FROM product p1 CROSS JOIN product p2;

也可通过另一种常见的写法,来实现这个结果。

SELECT p1.name AS name_1, p2.name AS name_2
FROM product p1, product p2;


统计结果:排列

name_1name_2
苹果橘子
苹果香蕉
橘子苹果
橘子香蕉
香蕉苹果
香蕉橘子

分析

排列不同于可重排序排列是不包含由相同元素构成的有序对。为了去掉这种由相同元素构成的对,需要加上一个条件,然后再进行连接运算。由于排除了相同的对,因此它的行数为 P23 = 6。

SELECT p1.name AS name_1, p2.name AS name_2
FROM product p1 CROSS JOIN product p2
WHERE p1.name <> p2.name;

排列-百度百科



统计结果:组合

name_1name_2
苹果橘子
香蕉苹果
香蕉橘子

分析

组合其实就是无序对,通过使用字符顺序进行排列,只与字符顺序比自己靠前的商品进行配对。这种方式结合了非等值连接自连接`,结果行数为C23 = 3。

SELECT p1.name AS name_1, p2.name AS name_2
FROM product p1 CROSS JOIN product p2
WHERE p1.name > p2.name;


问题描述:

查询出指定表中的重复数据

数据表格:product

rowid(行ID)name(商品名称)price(价格)
1苹果50
2橘子100
3橘子100
4橘子100
5香蕉80

统计结果

rowidname
3橘子
4橘子

分析

重复的数据表示为商品名称和价格相同,但行ID不同。通过使用非等值连接,便可以查询出来。

SELECT *
FROM product p1
WHERE EXISTS (SELECT *
             FROM product p2
             WHERE p1.name = p2.name
               AND p2.price = p2.price
			   AND p1.id > p2.id);


问题描述:

将以下商品按照价格从高到底排序,针对价格相同的商品位次, `rank_1` 为 `跳过之后的位次`,`rank_2` 为 `不跳过之后的位次`。

数据表格:product

name(商品名称)price(价格)
苹果50
橘子100
葡萄50
西瓜80
柠檬30
香蕉50

统计结果

namepricerank_1rank_2
橘子10011
西瓜8022
葡萄5033
香蕉5033
苹果5033
柠檬3064

分析

为了获取到价格从高到低名次,就需要计算出价格比自己高的记录条数,并将其作为自己的位次。

首先是价格最高的100,因为不存在比它高的价格,所以记录为0。加下来是价格第二高的80,比它高的价格只有100,所以记录为1。同样地,价格为50的时候返回2,为30的时候返回3。

集合价格比自己高的价格比自己高的价格的个数
S0100-0
S1801001
S250100,802
S330100,80,50,50,505
SELECT p1.name, p1.price,
	COUNT(p2.price) + 1 AS rank_1, -- 跳过之后的位次
	COUNT(DISTINCT p2.price) + 1 AS rank_2 -- 不跳过之后的位次
FROM product p1 LEFT OUTER JOIN product p2
  ON p1.price < p2.price
GROUP BY p1.name
ORDER BY COUNT(p2.price);

以上的 SQL 中通过使用 DISTINCT 关键字,当存在相同位次的记录时,就可以不跳过之后的位次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值