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

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 BYORDER 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在内容逻辑与叙事结构上应注意什么?
提成工资是否必须纳入社保和个税的缴费基数进行计算,法律是如何规定的?
提成工资是否必须纳入社保和个税的缴费基数进行计算,法律是如何规定的?
公交车内新增的智能显示屏,除了到站信息还能提供哪些实用服务?
公交车内新增的智能显示屏,除了到站信息还能提供哪些实用服务?
个人破产制度若在更多城市试点,它与个人征信记录之间是怎样的关系?
个人破产制度若在更多城市试点,它与个人征信记录之间是怎样的关系?
与客户或平台发生服务纠纷时,零工工作者可以通过哪些便捷途径寻求解决?
与客户或平台发生服务纠纷时,零工工作者可以通过哪些便捷途径寻求解决?
包头市正规殡葬服务公司%白事仪式,白事丧事服务
包头市正规殡葬服务公司%白事仪式,白事丧事服务
成分表里如果出现
成分表里如果出现"硫酸镁""氯化钾"字样,是不是说明这瓶水是人工加矿物质的?
洛阳市殡葬礼仪服务公司%白事告别会,丧葬一条龙服务
洛阳市殡葬礼仪服务公司%白事告别会,丧葬一条龙服务
目前对自动驾驶汽车进行安全测试和认证的机构,会影响责任认定吗?
目前对自动驾驶汽车进行安全测试和认证的机构,会影响责任认定吗?
公司倡导“奋斗文化”但未支付加班费,如何区分自愿付出与“隐形加班”?
公司倡导“奋斗文化”但未支付加班费,如何区分自愿付出与“隐形加班”?
如果因特殊情况(如紧急就医)未及时清理犬便,如何申诉以免误扣信用分?
如果因特殊情况(如紧急就医)未及时清理犬便,如何申诉以免误扣信用分?
朝阳市殡葬服务正规公司%丧葬乐队,正规丧葬服务公司
朝阳市殡葬服务正规公司%丧葬乐队,正规丧葬服务公司
九江市丧事摄像服务#殡葬服务热线,贴心服务
九江市丧事摄像服务#殡葬服务热线,贴心服务
为什么同样是
为什么同样是"发芽",土豆会被反复提醒注意,而红薯、生姜发芽却常常被认为问题不大?
商丘市殡葬服务一站式办理%丧葬录像,白事丧事服务
商丘市殡葬服务一站式办理%丧葬录像,白事丧事服务
艾草晒干后香味会变“沉”,这种气味变化跟你晾晒厚度、通风和光照强度有关吗?
艾草晒干后香味会变“沉”,这种气味变化跟你晾晒厚度、通风和光照强度有关吗?
株洲市殡礼吊唁#殡葬一条龙公司,服务好
株洲市殡礼吊唁#殡葬一条龙公司,服务好
老年公交卡什么时候能真正实现全国通用,跨省市乘车现在还需要重新办理吗?
老年公交卡什么时候能真正实现全国通用,跨省市乘车现在还需要重新办理吗?