增长速度需用lag()计算同比变化率,分母为0须用nullif()处理,且必须基于有序时间维度;找最快增长城市需两层窗口函数,生产环境建议用cte避免重复计算。

理解“增长速度”在SQL窗口函数中的实际含义
增长速度不是数据库内置概念,必须先定义清楚计算逻辑。常见做法是用 LAG() 取前一年人口(或GDP、用户数等指标),再算同比变化率:(current_value - prev_value) / NULLIF(prev_value, 0)。注意分母为0必须用 NULLIF() 拦住,否则直接报错 division by zero。
- 增长率字段必须基于有序时间维度(如
year),否则LAG()返回结果不可靠 - 若原始数据存在城市+年份重复,需先
GROUP BY city, year聚合,否则窗口计算会错乱 -
ORDER BY year必须写在OVER()子句里,不能只靠外部排序
用LAG()和ROW_NUMBER()组合定位最快增长城市
单纯算出增长率还不够,得找出“哪一年哪个城市的增速最高”。这时候需要两层窗口:第一层算增长率,第二层用 ROW_NUMBER() OVER (ORDER BY growth_rate DESC) 排名,再过滤 rn = 1。
SELECT city, year, growth_rate
FROM (
SELECT
city,
year,
(population - LAG(population) OVER (PARTITION BY city ORDER BY year)) * 1.0
/ NULLIF(LAG(population) OVER (PARTITION BY city ORDER BY year), 0) AS growth_rate,
ROW_NUMBER() OVER (ORDER BY
(population - LAG(population) OVER (PARTITION BY city ORDER BY year)) * 1.0
/ NULLIF(LAG(population) OVER (PARTITION BY city ORDER BY year), 0) DESC) AS rn
FROM city_population
WHERE year IN (2020, 2021, 2022)
) t
WHERE rn = 1;
- 不要重复写四遍
LAG()表达式——生产环境建议用 CTE 或子查询提前算好增长率字段 -
ROW_NUMBER()和RANK()效果不同:若多个城市并列最高增速,ROW_NUMBER()只返回一行,RANK()会都返回rank = 1 - 浮点精度问题:用
* 1.0或::DECIMAL显式转类型,避免整数除法截断
处理跨年缺失与城市维度不齐的问题
真实数据常有某城市缺2021年数据,导致 LAG() 返回 NULL,进而让整个增长率变 NULL。这不是bug,是预期行为,但容易被忽略。
- 先检查每个城市的年份连续性:
COUNT(*) OVER (PARTITION BY city)看是否覆盖全部目标年份 - 若允许“跳年”计算(如2020→2022),改用
LAG(population, 2)并同步调整分母,但语义已变为“两年复合增速”,需和业务对齐 - 用
FIRST_VALUE()或LAST_VALUE()替代LAG()仅在特定场景有效(比如固定取首尾两年),但无法表达逐年变化
最麻烦的其实是“城市列表动态变化”——新城市2022年才出现,没有前序年份可比。这种情况下,增速无定义,应主动过滤:WHERE LAG(population) OVER (PARTITION BY city ORDER BY year) IS NOT NULL。











