sql - MAX() OVER PARTITION 未按预期工作
问题描述
当我尝试使用一组记录获取字段的 MAX 值时遇到了一些问题,我希望你们中的一些人可以帮助我找出我做错了什么。
我正在尝试在订单中获取最昂贵行的商品的 ID。
鉴于此查询:
SELECT
orderHeader.orderKey, orderLines.lineKey, orderLines.itemKey, orderLines.OrderedQty,
orderLines.price, (orderLines.price*orderLines.OrderedQty) as LinePrice,
ROW_NUMBER() OVER(PARTITION BY orderHeader.orderKey ORDER BY orderLines.lineKey asc) AS [ItemLineNum],
ROW_NUMBER() OVER(PARTITION BY orderHeader.orderKey ORDER BY (orderLines.price*orderLines.OrderedQty) DESC) AS [LineMaxPriceNum],
max(orderLines.itemKey) OVER (PARTITION BY orderHeader.orderKey ORDER BY (orderLines.price*orderLines.OrderedQty) DESC) as [MaxPriceItem]
FROM
orderHeader inner join orderLines on orderHeader.orderKey=orderLines.orderKey
我得到这个结果: 查询结果
抱歉,由于我不允许在帖子中直接插入图片,我将尝试使用片段来格式化表格。
这些是结果
| orderKey | lineKey | itemKey | OrderedQty | Price | LinePrice | ItemLineNum | LineMaxPriceNum | MaxPriceItem |
|----------|---------|---------|------------|-------|-----------|-------------|-----------------|--------------|
| 176141 | 367038 | 15346 | 3 | 1000 | 3000 | 2 | 1 | 15346 |
| 176141 | 367037 | 15159 | 2 | 840 | 1680 | 1 | 2 | 15346 |
| 176141 | 367039 | 15374 | 5 | 100 | 500 | 3 | 3 | 15374 |
如您所见,对于相同的“orderKey”,我有三行(lineKey),每行都有不同的项目(itemKey)、不同的数量、不同的价格和不同的总成本(LinePrice)。我希望在 MaxPriceItem 列中具有较高“LinePrice”的项目的键,但结果是错误的。三行应该显示 15346 是最昂贵的项目,但最后一行是不正确的,我不明白为什么。此外,由同一表达式 (LineMaxPriceNum) 划分的 ROW_NUMBER 给了我正确的顺序。
如果我在 MAX 中更改 ORDER BY 的表达式,像这样(按“OrderedQty”排序):
SELECT
orderHeader.orderKey, orderLines.lineKey, orderLines.itemKey, orderLines.OrderedQty,
orderLines.price, (orderLines.price*orderLines.OrderedQty) as LinePrice,
ROW_NUMBER() OVER(PARTITION BY orderHeader.orderKey ORDER BY orderLines.lineKey asc) AS [ItemLineNum],
ROW_NUMBER() OVER(PARTITION BY orderHeader.orderKey ORDER BY (orderLines.price*orderLines.OrderedQty) DESC) AS [LineMaxPriceNum],
max(orderLines.itemKey) OVER (PARTITION BY orderHeader.orderKey ORDER BY orderLines.OrderedQty DESC) as [MaxPriceItem]
FROM
orderHeader inner join orderLines on orderHeader.orderKey=orderLines.orderKey
然后它工作:
| orderKey | lineKey | itemKey | OrderedQty | Price | LinePrice | ItemLineNum | LineMaxPriceNum | MaxPriceItem |
|----------|---------|---------|------------|-------|-----------|-------------|-----------------|--------------|
| 176141 | 367038 | 15346 | 3 | 1000 | 3000 | 2 | 1 | 15374 |
| 176141 | 367037 | 15159 | 2 | 840 | 1680 | 1 | 2 | 15374 |
| 176141 | 367039 | 15374 | 5 | 100 | 500 | 3 | 3 | 15374 |
“OrderedQty”最高的项目是 15374,因此结果是正确的。
如果我再次更改 MAX 中 ORDER BY 的表达式,如下所示(按“价格”排序):
SELECT
orderHeader.orderKey, orderLines.lineKey, orderLines.itemKey, orderLines.OrderedQty,
orderLines.price, (orderLines.price*orderLines.OrderedQty) as LinePrice,
ROW_NUMBER() OVER(PARTITION BY orderHeader.orderKey ORDER BY orderLines.lineKey asc) AS [ItemLineNum],
ROW_NUMBER() OVER(PARTITION BY orderHeader.orderKey ORDER BY (orderLines.price*orderLines.OrderedQty) DESC) AS [LineMaxPriceNum],
max(orderLines.itemKey) OVER (PARTITION BY orderHeader.orderKey ORDER BY orderLines.price DESC) as [MaxPriceItem]
FROM
orderHeader inner join orderLines on orderHeader.orderKey=orderLines.orderKey
然后它发生与第一个示例相同的情况,结果是错误的:
| orderKey | lineKey | itemKey | OrderedQty | Price | LinePrice | ItemLineNum | LineMaxPriceNum | MaxPriceItem |
|----------|---------|---------|------------|-------|-----------|-------------|-----------------|--------------|
| 176141 | 367038 | 15346 | 3 | 1000 | 3000 | 2 | 1 | 15346 |
| 176141 | 367037 | 15159 | 2 | 840 | 1680 | 1 | 2 | 15346 |
| 176141 | 367039 | 15374 | 5 | 100 | 500 | 3 | 3 | 15374 |
最高价格的商品是 15346,但最后一条记录的 MAX 没有显示这一点。
我在这里想念什么?为什么我会得到那些不同的结果?
抱歉,如果格式设置不正确,这是我的第一个问题,我已经尽力了。
提前感谢您能给我的任何帮助。
解决方案
我正在尝试在订单中获取最昂贵行的商品的 ID。
您误解了order by
窗口函数子句的用途;它旨在定义窗口框架,而不是比较值;max()
为您提供在窗口框架内作为参数给出的表达式的最大值。
另一方面,您想要itemKey
最昂贵的订单行。我认为这first_value()
会做你想要的:
first_value(orderLines.itemKey) over(
partition by orderHeader.orderKey
order by orderLines.price * orderLines.OrderedQty desc
) as [MaxPriceItem]
推荐阅读
- c++ - 什么是基于循环迭代几个元组的范围的简洁表示法
- java - 当我尝试使用 java FTPClient 从远程服务器删除文件时,我收到 500 作为回复代码
- javascript - 不通过 Node 应用程序访问 mongodb atlas 上的旧数据
- c++ - 如果系统内存足够,C++ 字符串是否可以包含无限数量的字符,并且 size_t 可以表示如此极端的长度吗?
- sonarqube - SonarQube 静态代码分析报告在本地声纳服务器而不是远程声纳服务器上发布
- mysql - MySQL 获取与其他记录有时间差的记录
- jquery - Laravel / Vuejs 链接共享
- listview - Oracle jet :: 在排序/过滤时在列表视图项(模型)中保留按钮设置状态
- javascript - 使用 await 和 async 承诺作用域
- javascript - 模块显示模式的参考错误