SQL中Lag()和LEAD()的用法示例詳解
前言
LAG() 和 LEAD() 是 SQL 中常用的窗口函數(shù),核心作用是在同一結(jié)果集中,根據(jù)指定排序規(guī)則,獲取當(dāng)前行“前面”或“后面”某行的數(shù)據(jù),無(wú)需進(jìn)行自連接,極大簡(jiǎn)化了“跨行取值”的邏輯。
一、核心定義與語(yǔ)法
兩者語(yǔ)法結(jié)構(gòu)完全一致,僅功能相反(LAG 取前,LEAD 取后)。
基本語(yǔ)法
LAG(目標(biāo)字段, 偏移量, 默認(rèn)值) OVER (
PARTITION BY 分組字段 -- 可選:按某字段分組,組內(nèi)獨(dú)立計(jì)算
ORDER BY 排序字段 [ASC/DESC] -- 必須:定義“前后”的排序規(guī)則
) AS 別名
LEAD(目標(biāo)字段, 偏移量, 默認(rèn)值) OVER (
PARTITION BY 分組字段 -- 可選
ORDER BY 排序字段 [ASC/DESC] -- 必須
) AS 別名
參數(shù)說(shuō)明
參數(shù) | 作用 |
目標(biāo)字段 | 要獲取的“前/后行”的字段(如金額、日期、姓名等) |
偏移量 | 可選,默認(rèn)值為 1,表示“前 1 行”(LAG)或“后 1 行”(LEAD) |
默認(rèn)值 | 可選,當(dāng)“前/后行不存在”時(shí)返回的值(如第一行用 LAG(1) 會(huì)返回 NULL) |
PARTITION BY | 可選,按指定字段分組,組內(nèi)單獨(dú)計(jì)算“前后行”(如按部門(mén)分組取員工數(shù)據(jù)) |
ORDER BY | 必須,定義組內(nèi)數(shù)據(jù)的排序順序,決定“前”和“后”的方向 |
二、典型應(yīng)用場(chǎng)景(附示例)
假設(shè)存在表 sales,存儲(chǔ)每日銷(xiāo)售數(shù)據(jù),結(jié)構(gòu)如下:
date | product | amount |
2024-01-01 | A | 100 |
2024-01-02 | A | 150 |
2024-01-03 | A | 200 |
2024-01-01 | B | 80 |
2024-01-02 | B | 120 |
場(chǎng)景 1:獲取“上一行/下一行”數(shù)據(jù)(基礎(chǔ)用法)
需求:查詢(xún)每個(gè)產(chǎn)品的每日銷(xiāo)售額,并顯示“前一天銷(xiāo)售額”和“后一天銷(xiāo)售額”。
SELECT
date,
product,
amount,
-- 獲取“同一產(chǎn)品”前 1 天的銷(xiāo)售額,無(wú)則返回 0
LAG(amount, 1, 0) OVER (
PARTITION BY product -- 按產(chǎn)品分組(不同產(chǎn)品不互相影響)
ORDER BY date ASC -- 按日期升序,“前”即“前一天”
) AS prev_day_amount,
-- 獲取“同一產(chǎn)品”后 1 天的銷(xiāo)售額,無(wú)則返回 0
LEAD(amount, 1, 0) OVER (
PARTITION BY product
ORDER BY date ASC -- 按日期升序,“后”即“后一天”
) AS next_day_amount
FROM sales;結(jié)果(清晰看到每行與前后行的關(guān)聯(lián)):
date | product | amount | prev_day_amount | next_day_amount |
2024-01-01 | A | 100 | 0 | 150 |
2024-01-02 | A | 150 | 100 | 200 |
2024-01-03 | A | 200 | 150 | 0 |
2024-01-01 | B | 80 | 0 | 120 |
2024-01-02 | B | 120 | 80 | 0 |
場(chǎng)景 2:計(jì)算“相鄰行差值”(如日環(huán)比)
需求:按產(chǎn)品計(jì)算每日銷(xiāo)售額的“環(huán)比增長(zhǎng)額”(當(dāng)日銷(xiāo)售額 - 前一日銷(xiāo)售額)。
SELECT
date,
product,
amount,
-- 當(dāng)日金額 - 前一天金額 = 環(huán)比增長(zhǎng)額
amount - LAG(amount, 1, 0) OVER (
PARTITION BY product
ORDER BY date ASC
) AS day_on_day_growth
FROM sales;結(jié)果:
date | product | amount | day_on_day_growth |
2024-01-01 | A | 100 | 100 |
2024-01-02 | A | 150 | 50 |
2024-01-03 | A | 200 | 50 |
2024-01-01 | B | 80 | 80 |
2024-01-02 | B | 120 | 40 |
場(chǎng)景 3:獲取“間隔多行”的數(shù)據(jù)(自定義偏移量)
需求:查詢(xún)每個(gè)產(chǎn)品的銷(xiāo)售額,并顯示“前 2 天”的銷(xiāo)售額(偏移量設(shè)為 2)。
SELECT
date,
product,
amount,
-- 偏移量=2:取“前 2 天”的數(shù)據(jù),無(wú)則返回 NULL
LAG(amount, 2) OVER (
PARTITION BY product
ORDER BY date ASC
) AS prev_2day_amount
FROM sales;結(jié)果(2024-01-03 的 A 產(chǎn)品,前 2 天是 2024-01-01 的 100):
date | product | amount | prev_2day_amount |
2024-01-01 | A | 100 | NULL |
2024-01-02 | A | 150 | NULL |
2024-01-03 | A | 200 | 100 |
2024-01-01 | B | 80 | NULL |
2024-01-02 | B | 120 | NULL |
三、關(guān)鍵注意事項(xiàng)
ORDER BY 必須存在:LAG/LEAD 依賴(lài)排序規(guī)則定義“前后”,缺少 ORDER BY 會(huì)報(bào)錯(cuò)或結(jié)果混亂。
PARTITION BY 分組隔離:無(wú) PARTITION BY 時(shí),全表視為一個(gè)“組”,跨行取值會(huì)跨越所有數(shù)據(jù)(如產(chǎn)品 A 和 B 的數(shù)據(jù)會(huì)互相取前后行)。
偏移量與默認(rèn)值:偏移量必須為非負(fù)整數(shù);默認(rèn)值不指定時(shí),“前后行不存在”會(huì)返回 NULL(可根據(jù)需求設(shè)為 0 或其他值)。
與自連接的區(qū)別:傳統(tǒng)“跨行取值”需用自連接(如 a.date = b.date + 1),但 LAG/LEAD 代碼更簡(jiǎn)潔、性能更高(尤其大數(shù)據(jù)量場(chǎng)景)。
總結(jié)
LAG() 和 LEAD() 是“跨行數(shù)據(jù)關(guān)聯(lián)”的高效工具,核心用于:
計(jì)算環(huán)比、同比(相鄰時(shí)間數(shù)據(jù)對(duì)比)
補(bǔ)全缺失的前后關(guān)聯(lián)信息(如前/后訂單、前/后員工數(shù)據(jù))
簡(jiǎn)化復(fù)雜的行與行之間的邏輯對(duì)比
核心邏輯:按分組、定排序、取前后,即可靈活應(yīng)對(duì)各類(lèi)“跨行取值”需求。
到此這篇關(guān)于SQL中Lag()和LEAD()用法的文章就介紹到這了,更多相關(guān)SQL中Lag()和LEAD()用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文解決連接MySQL報(bào)錯(cuò)is?not?allowed?to?connect?to?this?MySQL?
這篇文章主要給大家介紹了關(guān)于如何通過(guò)一文解決連接MySQL報(bào)錯(cuò)is?not?allowed?to?connect?to?this?MySQL?server的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08
Mysql數(shù)據(jù)表分區(qū)技術(shù)PARTITION淺析
這篇文章主要介紹了Mysql數(shù)據(jù)表分區(qū)技術(shù)PARTITION淺析,分別介紹了 Mysql 中的分區(qū)技術(shù) RANGE、LIST、 HASH,需要的朋友可以參考下2014-06-06
apache中訪問(wèn)不了偽靜態(tài)頁(yè)面的解決方法
apache中訪問(wèn)不了偽靜態(tài)頁(yè)面的解決方法,有需要的朋友可以參考下2013-02-02
MySQL事務(wù)保證數(shù)據(jù)一致性的核心講解
這篇文章主要介紹了MySQL事務(wù)實(shí)現(xiàn)保證數(shù)據(jù)一致性的原理,事務(wù)不是萬(wàn)能藥,它不能解決所有數(shù)據(jù)問(wèn)題,比如硬件物理?yè)p壞需要靠備份恢復(fù),但它是保障數(shù)據(jù)一致性的基礎(chǔ),沒(méi)有事務(wù),任何涉及多步操作的數(shù)據(jù)場(chǎng)景,都可能出現(xiàn)翻車(chē)風(fēng)險(xiǎn),需要的朋友可以參考下2025-10-10
Mysql 直接查詢(xún)存儲(chǔ)的Json字符串中的數(shù)據(jù)
本文主要介紹了Mysql直接查詢(xún)存儲(chǔ)的Json字符串中的數(shù)據(jù),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
ssm框架如何調(diào)用mysql存儲(chǔ)過(guò)程
這篇文章主要介紹了ssm框架如何調(diào)用mysql存儲(chǔ)過(guò)程,首先是建表,創(chuàng)建存儲(chǔ)過(guò)程,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-05-05
MySQL中多個(gè)left?join?on關(guān)聯(lián)條件的順序說(shuō)明
這篇文章主要介紹了MySQL中多個(gè)left?join?on關(guān)聯(lián)條件的順序說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
完美轉(zhuǎn)換MySQL的字符集 解決查看utf8源文件中的亂碼問(wèn)題
本人轉(zhuǎn)換過(guò)好多數(shù)據(jù)了,也用過(guò)了好多的辦法,個(gè)人感覺(jué)最好用的就是使用MySQL命令導(dǎo)出導(dǎo)入中將字符集轉(zhuǎn)換過(guò)去2011-11-11

