SQL 窗口函数 - 自上次 Max 以来的行数
Posted
技术标签:
【中文标题】SQL 窗口函数 - 自上次 Max 以来的行数【英文标题】:SQL Window Function - Number of Rows since last Max 【发布时间】:2019-07-27 00:42:35 【问题描述】:我正在尝试创建一个 SQL 查询,该查询将在过去 5 行中提取自 windows 函数中的最后一个最大值以来的行数。在下面的示例中,它将为第 8 行返回 2。最大值为 12,即第 8 行的 2 行。
对于第 6 行,它将返回 5,因为 7 的最大值在 5 行之外。
|ID | Date | Amount
| 1 | 1/1/2019 | 7
| 2 | 1/2/2019 | 3
| 3 | 1/3/2019 | 4
| 4 | 1/4/2019 | 1
| 5 | 1/5/2019 | 1
| 6 | 1/6/2019 | 12
| 7 | 1/7/2019 | 2
| 8 | 1/8/2019 | 4
我尝试了以下方法:
SELECT ID, date, MAX(amount)
OVER (ORDER BY date ASC ROWS 5 PRECEDING) mymax
FROM tbl
这让我达到最大值,但我无法有效地确定它有多少行。我能够在 SELECT 中使用多个变量来接近,但这似乎没有效率或可扩展性。
【问题讨论】:
以表格格式显示预期输出。 【参考方案1】:您可以计算累积最大值,然后在上面使用row_number()
。
所以:
select t.*,
row_number() over (partition by running_max order by date) as rows_since_last_max
from (select t.*,
max(amount) over (order by date rows between 5 preceding and current row) as running_max
from tbl t
) t;
我认为这适用于您的示例数据。如果您有重复,它可能无法正常工作。
在这种情况下,您可以使用日期算术:
select t.*,
datediff(day,
max(date) over (partition by running_max order by date),
date
) as days_since_most_recent_max5
from (select t.*,
max(amount) over (order by date rows between 5 preceding and current row) as running_max
from tbl t
) t;
编辑:
这里是一个使用行号的例子:
select t.*,
(seqnum - max(case when amount = running_amount then seqnum end) over (partition by running_max order by date)) as rows_since_most_recent_max5
from (select t.*,
max(amount) over (order by date rows between 5 preceding and current row) as running_max,
row_number() over (order by date) as seqnum
from tbl t
) t;
【讨论】:
感谢您的回复,但我仍然遇到问题。我的“金额”确实有重复的数字,这会导致问题。然后我尝试了您提供的第二个示例,但是我的源数据的日期存在差距。这会产生不准确的结果。我真的需要最近的最大行数而不是 datediff。任何额外的帮助将不胜感激。 @JDG 。 . .您明确声明您想要前五行,因此日期中的空白应该无关紧要。如果它们是一个问题,我建议您提出一个新的问题,并提供适当的样本数据、期望的结果和解释。 嗨,戈登。没错,它应该是前 5 行中的最大值。 datediff 函数计算日期之间的差异,而不是行中的差异。例如,日期可以按 10/1/2019、10/2/2019、10/5/2019、10/10/2019 的顺序排列。 datedff 将提供与行差异不匹配的“days_since_most_recent_max5”。 @JDG 。 . .在这种情况下,您可以使用id
而不是 date
- 如果您的 id 没有间隙并且始终递增 1。
是的,这就是我最初在您的第一个示例中尝试的方法。问题是查询的第一部分中有重复的“running_max”。当查询的第二部分查找 row_number 时,它选择了不正确的记录。在许多情况下,rows_since_last_max 返回的值超过 5。这是因为它在正确的实例之前找到了重复的 running_max。【参考方案2】:
应该是:
select *,ID-
(
SELECT ID
FROM
(
SELECT
ID,amount,
Maxamount =q.mymax
FROM
Table_4
) AS derived
WHERE
amount = Maxamount
) as result
from (
SELECT ID, date,
MAX(amount)
OVER (ORDER BY date ASC ROWS 5 PRECEDING) mymax
FROM Table_4
)as q
【讨论】:
以上是关于SQL 窗口函数 - 自上次 Max 以来的行数的主要内容,如果未能解决你的问题,请参考以下文章
错误:找不到要更新的行。自上次读取以来,某些值可能已更改。关于将提供程序从 SQLOLEDB 更改为 MSOLEDBSQL