sql - MAX() OVER PARTITION BY 没有按预期工作

标签 sql sql-server join max window-functions

当我尝试使用一组记录获取字段的最大值时遇到了一些问题,我希望你们中的一些人能帮助我找出我做错了什么。
我正在尝试获取订单中最昂贵行的商品 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

我得到这个结果: Results of Query

抱歉,因为我不允许直接在帖子中插入图片,我会尝试使用片段来格式化表格。
这些是结果

| 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 没有显示这一点。

我在这里错过了什么?为什么我得到那些不同的结果?

抱歉,如果格式设置不正确,这是我的第一个问题,我已经尽力了。

在此先感谢您能给我的任何帮助。

最佳答案

I'm trying to get the ID of the item of the most expensive line, within an order.

您误解了order by 子句对窗口函数的用途;它是用来定义窗口框架的,而不是用来比较值的; max() 为您提供窗口框架内作为参数给出的表达式的最大值。

另一方面,您需要最昂贵订单行的itemKey。我认为 first_value() 会做你想做的事:

first_value(orderLines.itemKey) over(
    partition by orderHeader.orderKey 
    order by orderLines.price * orderLines.OrderedQty desc
) as [MaxPriceItem]

关于sql - MAX() OVER PARTITION BY 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62173414/

相关文章:

MySQL 将多个子查询优化为嵌套内部连接?

sql - 按名称查找所有数据库对象?

sql - 如何修改 LEFT OUTER JOIN 以添加右侧表的过滤器

MySQL 通过 JOIN 选择没有有效订单的客户

php - 使用 JOIN 显示 friend 的帖子

PHP move_uploaded_file 上传视频到 MySQL 不工作

sql - 是否有任何缺点会阻碍您向表列添加索引?

java - 将字符串值传递给 SQL bigint 列

sql-server - 基于所有 "Key/Value"对完全匹配的内部连接两个表

mysql - 将 @jointable 与所有非唯一列一起使用