首页 > 数据库 >psql窗口函数 ​​ROW_NUMBER的应用

psql窗口函数 ​​ROW_NUMBER的应用

时间:2024-01-11 12:02:55浏览次数:30  
标签:psql JOIN NUMBER order 订单 客户 LEFT id ROW

我可以通过一个简单的例子来说明使用窗口函数 ROW_NUMBER() 结合 LEFT JOIN 来只映射(mapping)第一个匹配项的用法。

假设我们有两个表:orders 和 customers。我们想要连接这两个表,但只想要每个订单对应的第一个客户(如果有多个客户与同一订单相关联的话)。

使用窗口函数的情况:

  1. 表结构示例
  • orders 表:

order_id

product

1

Apple

2

Banana

3

Cherry

  • customers 表:

customer_id

order_id

name

100

1

Alice

101

1

Bob

102

2

Carol

  1. 目标
    对于每个订单,我们只想连接第一个客户。例如,对于订单1,虽然有Alice和Bob两个客户,但我们只想选择Alice(基于某种排序标准,例如customer_id)。
  2. SQL查询
    我们首先使用ROW_NUMBER()窗口函数为customers表中的每一行生成一个序号,按order_id分区,按customer_id排序。然后,我们将此结果与orders表进行LEFT JOIN,但只选择每个订单的第一个客户(即序号为1的行)。
WITH RankedCustomers AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY customer_id) AS rn
    FROM customers
)
SELECT o.order_id, o.product, rc.name
FROM orders o
LEFT JOIN RankedCustomers rc ON o.order_id = rc.order_id AND rc.rn = 1;
  1. 结果
    这个查询会返回每个订单和对应的第一个客户的名字。如果某个订单没有对应的客户,则该订单的客户名字为NULL。

order_id

product

name

1

Apple

Alice

2

Banana

Carol

3

Cherry

NULL

这个方法主要用于在进行LEFT JOIN时控制每个分组只映射一个匹配项,非常适用于处理一对多关系时只需获取一条记录的场景。

如果你不使用窗口函数,而是直接进行 LEFT JOIN,结果将会不同,尤其是在处理一对多关系时。在你的例子中,如果直接使用 LEFT JOIN 连接 orders 表和 customers 表,结果将包括每个订单与每个相应客户的所有匹配项。

不使用窗口函数的情况:

假设你执行以下查询:

SELECT o.order_id, o.product, c.name
FROM orders o
LEFT JOIN customers c ON o.order_id = c.order_id;

这将产生以下结果:

order_id

product

name

1

Apple

Alice

1

Apple

Bob

2

Banana

Carol

3

Cherry

NULL

分析:

  • 对于 order_id 1,有两个匹配的客户:Alice 和 Bob。因此,这个订单会出现两次,每次与不同的客户。
  • 对于 order_id 2,只有一个匹配的客户:Carol。
  • 对于 order_id 3,没有匹配的客户,所以客户名为 NULL。

结果对比:

  • 使用窗口函数:你只得到每个订单的第一个客户,总共3条记录。
  • 不使用窗口函数:你得到所有匹配的订单和客户组合,总共4条记录。

标签:psql,JOIN,NUMBER,order,订单,客户,LEFT,id,ROW
From: https://blog.51cto.com/u_14480405/9195453

相关文章

  • js Number类型
    Number是对应数值的引用类型。要创建一个Number对象,就使用Number构造函数并传入一个数值,如下例所示:letnumberObject=newNumber(10);与Boolean类型一样,Number类型重写了valueOf()、toLocaleString()和toString()方法。valueOf()方法返回Number对象表示的原始数值......
  • js Number类型
    与Boolean对象类似,Number对象也为数值提供了重要能力。但是,考虑到两者存在同样的潜在问题,因此并不建议直接实例化Number对象。在处理原始数值和引用数值时,typeof和instacnceof操作符会返回不同的结果,如下所示:letnumberObject=newNumber(10);letnumberValue=1......
  • Apple iWork(Pages、Numbers、Keynote)11.0 发布
    苹果今天将其专为iOS和macOS设备设计的iWork应用套件更新为版本11,引入了许多新功能和改进功能。Pages文稿。文档高手,精美不言而喻。进一步了解Pages文稿>Numbers表格。精妙的电子表格,联手做。进一步了解Numbers表格>Keynote讲演。令人难忘的出色提案,轻松打造。进......
  • JS 根据文件Magic Number判断文件是否是图片
    原理:检测文件的MagicNumber代码示例:varpngMagic=[0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a];varjpeg_jfif=[0x4a,0x46,0x49,0x46];varjpeg_exif=[0x45,0x78,0x69,0x66];varjpegMagic=[0xFF,0xD8,0xFF,0xE0];var......
  • Applied Statistics - 应用统计学习 - numpy array交换两行 ? How to Swap Two Rows in
    https://www.statology.org/qualitative-vs-quantitative-variables/https://www.statology.org/numpy-swap-rows/HowtoSwapTwoRowsinaNumPyArray(WithExample)YoucanusethefollowingbasicsyntaxtoswaptworowsinaNumPyarray:some_array[[0,3],:......
  • 窄带物联网(Narrow Band Internet of Things, NB-IoT)
    NB-IoT_百度百科https://baike.baidu.com/item/NB-IoT/19420464窄带物联网(NarrowBandInternetofThings,NB-IoT)成为万物互联网络的一个重要分支。NB-IoT构建于蜂窝网络,只消耗大约180kHz的带宽,可直接部署于GSM网络、UMTS网络或LTE网络,以降低部署成本、实现平滑升级。 [1]N......
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之线性布局容器Row组件
    鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之线性布局容器Row组件一、操作环境操作系统: Windows10专业版、IDE:DevEcoStudio3.1、SDK:HarmonyOS3.1二、Row组件沿水平方向布局容器。子组件可以包含子组件。接口Row(value?:{space?:string|number})参数参数名参数类型必填默认值参数......
  • Qt小技巧17.使用魔法数(Magic Number)
    1什么是魔法数?当使用QDataStream进行数据流读写时,魔法数(MagicNumber)是用于标识特定文件格式或数据结构的固定数值或字节序列。魔法数是一个固定的数值或字节序列,用于识别特定文件格式或数据表示方式,在读取操作中起到了一个检测标识的作用,可以帮助确定所读取的文件是否符合预......
  • 『LeetCode』9. 回文数 Palindrome Number
    题目描述给你一个整数x,如果x是一个回文整数,返回true;否则,返回false。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121是回文,而123不是。示例1:输入:x=121输出:true示例2:输入:x=-121输出:false解释:从左向右读,为-121。从右向左读,为121-。因此......
  • oracle中排序分析函数row_number()、rank()、dense_rank() 的区别
    row_number()产生的序号不会重复,即1、2、3...rank()产生的序号会重复,但是会跳号,出现1、2、2、4...的情况dense_rank()产生的序号会重复,不会跳号,会出现1、2、2、3的情况而普通的rownum是一个伪列,与你的orderby是没有关系的SELECTrow_number()over(ORDERBYac.check_number......