17370845950

sql 中 min () over order by 用法_sql 中 min () over 按序取最小值技巧

要按顺序取最小值需结合order by与rows between子句,语法为:min(column_name) over (order by order_column rows between unbounded preceding and current row),1. min(column_name)指定计算最小值的列;2. over()定义窗口范围;3. order by指定排序方式;4. rows between表示从第一行到当前行。此方法可用于分析趋势、累计统计等场景,如计算历史最低销售额、股票最低价、玩家最佳成绩等,使用时注意排序字段应唯一或有序,建议显式指定窗口范围以确保准确性。

在 SQL 中,MIN() OVER() 通常用来计算窗口内的最小值。但如果你希望它“按顺序取最小值”,就需要结合 ORDER BY 子句来控制窗口的排序和范围。

简单来说:你想让每一行都看到前面所有数据中的最小值,而不是整个字段的全局最小值。这在分析趋势、累计统计等场景中非常有用。


如何用 MIN() OVER() 结合 ORDER BY

基本语法如下:

MIN(column_name) OVER (ORDER BY order_column ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
  • MIN(column_name) 是你要找的最小值列。
  • OVER() 定义了窗口函数的范围。
  • ORDER BY order_column 指定了排序方式。
  • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 表示从第一行开始,到当前行为止

这样写的意思是:每一行都会看到从第一行到当前行之间所有数据的最小值

举个例子:

假设你有如下销售记录表(sales):

date amount
2025-01-01 100
2025-01-02 80
2025-01-03 90
2025-01-04 70

你想知道每一天之前(包括当天)的最低销售额,可以这样写:

SELECT 
  date,
  amount,
  MIN(amount) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS min_so_far
FROM sales;

结果会是:

date amount min_so_far
2025-01-01 100 100
2025-01-02 80 80
2025-01-03 90 80
2025-01-04 70 70

可以看到,min_so_far 是随着日期递增不断更新的“历史最小值”。


注意事项与常见问题

  • 排序字段必须唯一或有序:如果 ORDER BY 的字段有重复值,可能会影响窗口范围的划分,导致结果不准确。
  • 默认窗口范围不一定符合预期:如果不加 ROWS BETWEEN ...,有些数据库默认只包括从第一行到当前行的所有行,但有些则不同。建议显式指定范围更稳妥。
  • 分区字段可选:如果你的数据需要分组处理(比如每个用户单独计算),可以加上 PARTITION BY user_id

例如:

MIN(amount) OVER (PARTITION BY user_id ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)

实际应用场景

这种技巧常用于:

  • 股票价格走势中计算“历史最低价”
  • 销售数据分析中查看“截止某天为止的最低销量”
  • 游戏排行榜中记录玩家的历史最佳成绩

只要涉及到随时间变化的累计最小值,都可以考虑使用这个方法。


基本上就这些,虽然看起来有点复杂,但其实逻辑很简单:先排好序,再定义窗口范围,然后取最小值。掌握后你会发现它真的很实用。