SELECT (SELECT COUNT(order_id) FROM orderform A WHERE A.order_id>=B.order_id) 编号,order_id,order_sn,total_amount FROM orderform B ORDER BY 1;
SQL 自连接排名查询代码重新讲解
一、代码整体结构
sql
SELECT (SELECT COUNT(order_id) FROM orderform A WHERE A.order_id >= B.order_id) 编号, order_id, order_sn, total_amountFROM orderform B ORDER BY 1;
二、这段代码的作用
按 order_id 从大到小生成排名编号(编号越小排名越高)
| 排名 | order_id | 说明 |
|---|---|---|
| 1 | 最大的 order_id | 第1名 |
| 2 | 第二大的 order_id | 第2名 |
| 3 | 第三大的 order_id | 第3名 |
| ... | ... | ... |
三、逐部分讲解
第1-4行:子查询(核心排名逻辑)
sql
(SELECT COUNT(order_id) FROM orderform A WHERE A.order_id >= B.order_id) 编号
这是一个相关子查询(Correlated Subquery),为外层查询的每一行计算一个排名编号。
| 部分 | 含义 |
|---|---|
SELECT COUNT(order_id) | 统计符合条件的订单数量 |
FROM orderform A | 给内层表起别名 A |
WHERE A.order_id >= B.order_id | 统计 order_id 大于等于当前行 order_id 的记录数 |
) 编号 | 子查询结束,将结果列命名为"编号" |
第5行:外层查询的字段
sql
order_id, order_sn, total_amount
| 字段 | 含义 |
|---|---|
order_id | 订单编号 |
order_sn | 订单流水号 |
total_amount | 订单总金额 |
第6行:数据来源与排序
sql
FROM orderform B ORDER BY 1;
| 部分 | 含义 |
|---|---|
FROM orderform B | 从订单表查询,起别名 B |
ORDER BY 1 | 按查询结果的第1列(即"编号"列)升序排序 |
四、核心原理:相关子查询如何计算排名?
假设原表数据
order_id | order_sn | total_amount |
1 | SN001 | 100 |
2 | SN002 | 200 |
3 | SN003 | 150 |
4 | SN004 | 300 |
执行过程
外层查询逐行读取 orderform B,每读一行,就执行一次子查询:
第1行:B.order_id = 1
sql
SELECT COUNT(order_id) FROM orderform A WHERE A.order_id >= 1
统计
order_id >= 1的记录数符合条件的 order_id:1、2、3、4 → 共 4 条
子查询结果:4
第2行:B.order_id = 2
sql
SELECT COUNT(order_id) FROM orderform A WHERE A.order_id >= 2
符合条件的 order_id:2、3、4 → 共 3 条
子查询结果:3
第3行:B.order_id = 3
符合条件的 order_id:3、4 → 共 2 条
第4行:B.order_id = 4
符合条件的 order_id:4 → 共 1 条
五、计算后的中间结果(未排序)
编号(计算值) | order_id | order_sn | total_amount |
4 | 1 | SN001 | 100 |
3 | 2 | SN002 | 200 |
2 | 3 | SN003 | 150 |
1 | 4 | SN004 | 300 |
此时编号是倒序的:order_id 越大,编号越小(因为满足 >= 条件的记录越少)。
六、ORDER BY 1 排序后的最终结果
ORDER BY 1 按第1列(编号)升序排序后:
编号 | order_id | order_sn | total_amount |
1 | 4 | SN004 | 300 |
2 | 3 | SN003 | 150 |
3 | 2 | SN002 | 200 |
4 | 1 | SN001 | 100 |
最终效果:
编号从小到大:1、2、3、4
order_id 从大到小:4、3、2、1
编号 = 排名(1是最高排名,对应最大的 order_id)
七、完整执行流程图
text
┌─────────────────────────────────────────────────────────────┐ │ 步骤1:外层查询逐行读取,内层子查询计算编号 │ ├─────────────────────────────────────────────────────────────┤ │ B.order_id=1 → 子查询统计 >=1 → 结果=4 → (4,1,SN001,100) │ │ B.order_id=2 → 子查询统计 >=2 → 结果=3 → (3,2,SN002,200) │ │ B.order_id=3 → 子查询统计 >=3 → 结果=2 → (2,3,SN003,150) │ │ B.order_id=4 → 子查询统计 >=4 → 结果=1 → (1,4,SN004,300) │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 步骤2:ORDER BY 1 按编号列升序排序 │ ├─────────────────────────────────────────────────────────────┤ │ 编号=1 → (1,4,SN004,300) │ │ 编号=2 → (2,3,SN003,150) │ │ 编号=3 → (3,2,SN002,200) │ │ 编号=4 → (4,1,SN001,100) │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 最终结果 │ ├─────────────────────────────────────────────────────────────┤ │ 编号=1(最高排名)对应 order_id=4(最大订单号) │ │ 编号=2 对应 order_id=3 │ │ 编号=3 对应 order_id=2 │ │ 编号=4 对应 order_id=1(最小订单号) │ └─────────────────────────────────────────────────────────────┘
八、如何改为正序排名(order_id 从小到大编号为1)?
只需把 >= 改为 <=:
sql
SELECT (SELECT COUNT(order_id) FROM orderform A WHERE A.order_id <= B.order_id) 编号, order_id, order_sn, total_amountFROM orderform B ORDER BY 1;
结果:
| 编号 | order_id |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
九、ORDER BY 1 的含义
| 写法 | 含义 |
|---|---|
ORDER BY 1 | 按 SELECT 列表中的第1列排序 |
ORDER BY 编号 | 按列名排序(等价) |
ORDER BY 1 DESC | 按第1列降序排序 |
sql
-- 这三种写法等价(第1列是"编号")ORDER BY 1ORDER BY 编号ORDER BY (SELECT COUNT(order_id) FROM orderform A WHERE A.order_id >= B.order_id)
十、总结
| 问题 | 答案 |
|---|---|
| 这段代码做什么? | 按 order_id 从大到小生成排名编号 |
| 编号顺序是什么? | 最终显示:从小到大(1,2,3,4) |
| 为什么编号是从小到大? | 因为 ORDER BY 1 按编号列升序排序 |
| 子查询计算出的原始编号顺序? | 从大到小(4,3,2,1) |
ORDER BY 1 什么意思? | 按 SELECT 列表的第1列升序排序 |
| 如何改为 order_id 从小到大排名? | 把 >= 改为 <= |
一句话总结:这段代码通过相关子查询统计 A.order_id >= B.order_id 的记录数来计算编号——order_id 越大,满足条件的记录越少,计算出的编号越小(4,3,2,1);再通过 ORDER BY 1 按编号升序排序,最终显示为编号从小到大(1,2,3,4),对应 order_id 从大到小(4,3,2,1),实现按 order_id 降序排名