在业务数据分析中,统计连续三个月销售增长的客户是评估客户价值、挖掘高潜力客户的核心需求。传统实现方式多采用自连接关联多个月的销售数据,不仅SQL语句冗长,在数据量较大时性能也会明显下降。使用LAG窗口函数可以简化这个逻辑,通过一次扫描数据就能完成相邻月份的销售对比。

LAG函数基础用法
LAG是SQL中的窗口函数,作用是获取当前行之前指定偏移量的行的数据。它的基本语法如下:
-- LAG函数基础语法 LAG(列名, 偏移量, 默认值) OVER (PARTITION BY 分组列 ORDER BY 排序列)
其中偏移量表示往前取第几行的数据,默认值为1;如果往前没有对应的行,会返回设置的默认值,不设置则默认返回NULL。PARTITION BY用来划分数据分组,比如按客户分组;ORDER BY用来指定组内的排序规则,比如按月份升序排列。
连续三个月销售增长判断逻辑
要判断某个客户是否连续三个月销售增长,需要依次对比相邻三个月的销售额:
- 当月销售额 大于 上一个月销售额
- 上一个月销售额 大于 上上一个月销售额
通过两次调用LAG函数,分别获取上一个月和上上个月的销售额,就能同时完成这两组对比,不需要多次关联表。
完整实现示例
假设我们有销售表sales_data,表结构如下:
| 列名 | 类型 | 说明 |
|---|---|---|
| customer_id | INT | 客户ID |
| sale_month | DATE | 销售月份,格式为YYYY-MM-01 |
| sale_amount | DECIMAL(10,2) | 当月销售额 |
下面的SQL语句可以查询出所有连续三个月销售增长的客户:
-- 计算连续三个月销售增长的客户
WITH month_sale AS (
-- 先按客户和月份汇总销售额,避免单月多笔订单的干扰
SELECT
customer_id,
sale_month,
SUM(sale_amount) AS total_sale
FROM sales_data
GROUP BY customer_id, sale_month
),
sale_lag AS (
SELECT
customer_id,
sale_month,
total_sale,
-- 获取上一个月的销售额,偏移量1
LAG(total_sale, 1) OVER (PARTITION BY customer_id ORDER BY sale_month) AS last_month_sale,
-- 获取上上个月的销售额,偏移量2
LAG(total_sale, 2) OVER (PARTITION BY customer_id ORDER BY sale_month) AS last_two_month_sale
FROM month_sale
)
SELECT DISTINCT customer_id
FROM sale_lag
-- 判断连续三个月增长:当前月>上月,上月>上上月
WHERE total_sale > last_month_sale
AND last_month_sale > last_two_month_sale
-- 排除上个月或上上个月没有数据的情况
AND last_month_sale IS NOT NULL
AND last_two_month_sale IS NOT NULL
ORDER BY customer_id;
逻辑说明
首先用CTE month_sale对每个客户每个月的销售额做汇总,确保每个月每个客户只有一条销售记录。接着在sale_lag中通过两次LAG调用,分别拿到当前客户前1个月和前2个月的销售额。最后在筛选条件中同时判断三次销售额的递增关系,并且排除偏移后取到NULL的情况,避免因为客户某个月没有销售记录导致的误判。
注意事项
- 如果销售月份不是连续的,需要先补全月份数据,否则LAG取到的会是相邻有数据的月份,不是自然月相邻的月份
- 不同数据库的LAG函数语法基本一致,上述代码在MySQL 8.0+、PostgreSQL、SQL Server等主流数据库都可以直接运行
- 如果需要统计连续N个月增长,只需要增加LAG的调用次数,调整对应的对比条件即可