欢迎光临殡葬白事网
详情描述

LAG() 和 LEAD() 的用法:

一、基本概念

这两个函数用于访问结果集中当前行之前或之后的行数据,而无需使用自连接。

1. LAG() - 获取前一行的值

LAG(column, offset, default_value) OVER (
    [PARTITION BY partition_expression]
    ORDER BY order_expression
)

2. LEAD() - 获取后一行的值

LEAD(column, offset, default_value) OVER (
    [PARTITION BY partition_expression]
    ORDER BY order_expression
)

二、参数详解

参数 说明
column 要访问的列名
offset 偏移量(默认1,可选)
default_value 当没有前/后行时的默认值(可选)
PARTITION BY 分区子句,在每个分区内独立计算
ORDER BY 排序子句,决定行的前后顺序

三、使用示例

示例数据

CREATE TABLE sales (
    sale_date DATE,
    product VARCHAR(50),
    amount DECIMAL(10,2)
);

INSERT INTO sales VALUES
('2024-01-01', 'A', 100),
('2024-01-02', 'A', 150),
('2024-01-03', 'A', 120),
('2024-01-01', 'B', 200),
('2024-01-02', 'B', 180),
('2024-01-03', 'B', 220);

1. 基本用法

-- 获取前一天的销售额
SELECT 
    sale_date,
    product,
    amount,
    LAG(amount) OVER (PARTITION BY product ORDER BY sale_date) as prev_amount,
    -- 计算日环比增长率
    ROUND((amount - LAG(amount) OVER (PARTITION BY product ORDER BY sale_date)) 
          / LAG(amount) OVER (PARTITION BY product ORDER BY sale_date) * 100, 2) as growth_rate
FROM sales
ORDER BY product, sale_date;

2. 指定偏移量

-- 获取前两天(偏移量为2)的数据
SELECT 
    sale_date,
    product,
    amount,
    LAG(amount, 2) OVER (PARTITION BY product ORDER BY sale_date) as amount_2days_ago,
    LEAD(amount, 2, 0) OVER (PARTITION BY product ORDER BY sale_date) as amount_2days_later
FROM sales;

3. 设置默认值

SELECT 
    sale_date,
    product,
    amount,
    -- 当没有前一天数据时,使用0作为默认值
    LAG(amount, 1, 0) OVER (PARTITION BY product ORDER BY sale_date) as prev_amount,
    -- 当没有后一天数据时,使用NULL作为默认值
    LEAD(amount, 1, NULL) OVER (PARTITION BY product ORDER BY sale_date) as next_amount
FROM sales;

四、实际应用场景

1. 计算环比/同比

-- 计算月度环比
WITH monthly_sales AS (
    SELECT 
        DATE_TRUNC('month', sale_date) as month,
        SUM(amount) as total_amount
    FROM sales
    GROUP BY DATE_TRUNC('month', sale_date)
)
SELECT 
    month,
    total_amount,
    LAG(total_amount) OVER (ORDER BY month) as prev_month_amount,
    ROUND((total_amount - LAG(total_amount) OVER (ORDER BY month)) 
          / LAG(total_amount) OVER (ORDER BY month) * 100, 2) as mom_growth
FROM monthly_sales;

2. 查找连续变化

-- 查找销售额连续下降的产品
WITH sales_trend AS (
    SELECT 
        sale_date,
        product,
        amount,
        LAG(amount) OVER (PARTITION BY product ORDER BY sale_date) as prev_amount
    FROM sales
)
SELECT *
FROM sales_trend
WHERE amount < prev_amount;  -- 当前销售额小于前一天

3. 计算时间间隔

-- 计算用户连续登录的时间间隔
SELECT 
    user_id,
    login_date,
    LAG(login_date) OVER (PARTITION BY user_id ORDER BY login_date) as last_login,
    DATEDIFF(day, 
             LAG(login_date) OVER (PARTITION BY user_id ORDER BY login_date), 
             login_date) as days_between_logins
FROM user_logins;

4. 数据填充(向前/向后填充)

-- 向前填充缺失值
SELECT 
    date,
    COALESCE(value, 
             LAG(value) IGNORE NULLS OVER (ORDER BY date)) as filled_value
FROM data_with_nulls;

五、与相关函数的对比

函数 方向 是否必须排序 典型用途
LAG() 向前看(之前) 是 访问前一行的值
LEAD() 向后看(之后) 是 访问后一行的值
FIRST_VALUE() 分区第一行 可选 获取分区第一个值
LAST_VALUE() 分区最后一行 可选 获取分区最后一个值

六、性能优化建议

合理使用索引:确保 PARTITION BY 和 ORDER BY 的列有索引 避免多层嵌套:尽量减少窗口函数的嵌套层级 使用CTE或子查询:复杂计算分步骤进行 限制窗口范围:使用 ROWS BETWEEN 子句限制计算范围

七、常见注意事项

ORDER BY 是关键:必须指定 ORDER BY 才能确定行的前后顺序 默认值处理:注意 NULL 值的处理,使用 COALESCE() 或默认值参数 分区边界:LAG() 和 LEAD() 不会跨越分区边界 性能影响:大量数据时,窗口函数可能有性能开销

八、复杂示例:计算移动平均

-- 计算3天的移动平均
SELECT 
    sale_date,
    product,
    amount,
    AVG(amount) OVER (
        PARTITION BY product 
        ORDER BY sale_date 
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) as moving_avg_3days,
    -- 使用LAG和LEAD手动计算
    (LAG(amount, 2, 0) OVER (PARTITION BY product ORDER BY sale_date) +
     LAG(amount, 1, 0) OVER (PARTITION BY product ORDER BY sale_date) +
     amount) / 3.0 as manual_moving_avg
FROM sales;

这两个函数是时间序列分析、趋势计算和数据对比的强大工具,掌握它们能大大简化许多复杂的SQL查询。

相关帖子
婚丧假最早来源于什么时代背景,为什么传统表述会给
婚丧假最早来源于什么时代背景,为什么传统表述会给"一至三天"这种弹性区间?
除了美观,一份优秀的PPT在内容逻辑与叙事结构上应注意什么?
除了美观,一份优秀的PPT在内容逻辑与叙事结构上应注意什么?
提成工资是否必须纳入社保和个税的缴费基数进行计算,法律是如何规定的?
提成工资是否必须纳入社保和个税的缴费基数进行计算,法律是如何规定的?
公交车内新增的智能显示屏,除了到站信息还能提供哪些实用服务?
公交车内新增的智能显示屏,除了到站信息还能提供哪些实用服务?
个人破产制度若在更多城市试点,它与个人征信记录之间是怎样的关系?
个人破产制度若在更多城市试点,它与个人征信记录之间是怎样的关系?
开封市殡葬服务公司%丧葬灵堂服务,丧事白事一条龙服务
开封市殡葬服务公司%丧葬灵堂服务,丧事白事一条龙服务
办理押证不押车贷款,年化利率与月管理费换算公式要懂
办理押证不押车贷款,年化利率与月管理费换算公式要懂
清远市殡葬服务公司一条龙办理%殡葬跟拍录像,丧葬服务一条龙
清远市殡葬服务公司一条龙办理%殡葬跟拍录像,丧葬服务一条龙
贷款买车期限怎么定最省?利息总额最小化计算法
贷款买车期限怎么定最省?利息总额最小化计算法
盘锦市殡葬公司电话%丧礼跟拍录像,丧事白事一条龙
盘锦市殡葬公司电话%丧礼跟拍录像,丧事白事一条龙
黄冈市殡礼布置#丧葬一条龙服务办理,合理的价格
黄冈市殡礼布置#丧葬一条龙服务办理,合理的价格
平顶山市殡葬公司电话%白事追思会策划,丧事服务
平顶山市殡葬公司电话%白事追思会策划,丧事服务
冬季是否适合洗冷水澡,在低温环境下进行需要注意哪些特殊事项?
冬季是否适合洗冷水澡,在低温环境下进行需要注意哪些特殊事项?
强制国标要求车企建立全生命周期安全保障,对我们用车意味着什么呢?
强制国标要求车企建立全生命周期安全保障,对我们用车意味着什么呢?
汽车贷款期限能否延期?遇到困难如何延长还款期
汽车贷款期限能否延期?遇到困难如何延长还款期
贵港市正规殡葬公司%殡葬灵棚,殡仪服务
贵港市正规殡葬公司%殡葬灵棚,殡仪服务
运城市丧葬告别会#办理丧葬服务,收费透明
运城市丧葬告别会#办理丧葬服务,收费透明
漳州市殡葬服务一条龙%殡葬悼念会布置,丧事白事一条龙服务
漳州市殡葬服务一条龙%殡葬悼念会布置,丧事白事一条龙服务
益阳市殡葬追思会布置#殡葬一条龙价格,安全可靠
益阳市殡葬追思会布置#殡葬一条龙价格,安全可靠
公积金转移是否意味着所有余额和缴费记录都能无缝转入新账户?
公积金转移是否意味着所有余额和缴费记录都能无缝转入新账户?