最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文深入解析Mysql的開窗函數(shù)(易懂版)

 更新時(shí)間:2025年09月24日 09:37:44   作者:不輝放棄  
在MySQL中窗口函數(shù)是一類非常強(qiáng)大的函數(shù),它們?cè)试S你在不改變表數(shù)據(jù)的情況下,對(duì)數(shù)據(jù)進(jìn)行復(fù)雜的分析和計(jì)算,這篇文章主要介紹了Mysql開窗函數(shù)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

SQL 開窗函數(shù)(Window Function)是一種強(qiáng)大的分析工具,它能在保留原有數(shù)據(jù)行的基礎(chǔ)上,對(duì) "窗口"(指定范圍的行集合)進(jìn)行聚合、排名或分析計(jì)算,解決了傳統(tǒng)GROUP BY聚合會(huì)合并行的局限性。

一、開窗函數(shù)的核心特點(diǎn)

  • 不合并行:與GROUP BY不同,開窗函數(shù)計(jì)算后會(huì)保留所有原始行,只是為每行附加一個(gè)計(jì)算結(jié)果。
  • 窗口定義:通過(guò)OVER()子句定義 "窗口"(即計(jì)算范圍),可按條件分區(qū)、排序或限定行范圍。
  • 適用場(chǎng)景:排名(如 top N)、累計(jì)計(jì)算(如累計(jì)求和)、移動(dòng)分析(如近 3 天平均值)、前后行數(shù)據(jù)獲取等。

二、基本語(yǔ)法結(jié)構(gòu)

開窗函數(shù)的通用語(yǔ)法:

函數(shù)名(參數(shù)) OVER (
  [PARTITION BY 分區(qū)列1, 分區(qū)列2...]  -- 可選:按列分組,每組獨(dú)立計(jì)算
  [ORDER BY 排序列1 [ASC|DESC], ...]  -- 可選:分區(qū)內(nèi)的排序方式
  [ROWS | RANGE 窗口范圍]  -- 可選:定義窗口的具體行范圍(行級(jí)窗口)
)
  • 函數(shù)名:可以是排名函數(shù)(RANK()、ROW_NUMBER()等)、聚合函數(shù)(SUM()、AVG()等)或分析函數(shù)(LAG()、LEAD()等)。
  • OVER()子句:核心部分,用于定義 "窗口" 的規(guī)則。

三、OVER()子句詳解

1. PARTITION BY:分區(qū)(分組)

  • 作用:將數(shù)據(jù)按指定列分成多個(gè)獨(dú)立的 "分區(qū)",開窗函數(shù)在每個(gè)分區(qū)內(nèi)單獨(dú)計(jì)算(類似GROUP BY的分組,但不合并行)。
  • 示例:按 "部門" 分區(qū),每個(gè)部門內(nèi)部獨(dú)立計(jì)算工資排名。

2. ORDER BY:分區(qū)內(nèi)排序

  • 作用:指定分區(qū)內(nèi)的行排序規(guī)則,影響排名函數(shù)的結(jié)果和窗口范圍的界定。
  • 注意:若不指定PARTITION BY,則全表視為一個(gè)分區(qū),按ORDER BY整體排序。

3. ROWS | RANGE:窗口范圍(行級(jí)窗口)

  • 作用:在分區(qū)內(nèi),進(jìn)一步限定參與計(jì)算的行范圍(如 "當(dāng)前行 + 前 2 行 + 后 1 行")。
  • 關(guān)鍵字:
    • ROWS:基于物理行數(shù)界定范圍(如 "前 2 行")。
    • RANGE:基于值的邏輯范圍界定(如 "值在當(dāng)前行 ±10 以內(nèi)的行"),僅支持?jǐn)?shù)值 / 日期類型。
  • 常用范圍表達(dá)式:
    • UNBOUNDED PRECEDING:分區(qū)的第一行
    • CURRENT ROW:當(dāng)前行
    • n PRECEDING:當(dāng)前行之前的第 n 行
    • n FOLLOWING:當(dāng)前行之后的第 n 行
    • 組合示例:ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING(當(dāng)前行 + 前 2 行 + 后 1 行)

四、常用開窗函數(shù)分類及示例

以下示例基于員工表employee,結(jié)構(gòu)如下:

idnamedepartmentsalaryhire_date
1張三技術(shù)部80002020-01-15
2李四技術(shù)部90002019-03-20
3王五技術(shù)部90002018-05-10
4趙六市場(chǎng)部70002021-02-05
5錢七市場(chǎng)部85002020-08-18

1. 排名函數(shù)(用于生成排名)

(1)ROW_NUMBER():生成唯一序號(hào)

  • 功能:為分區(qū)內(nèi)的每行分配一個(gè)連續(xù)的唯一序號(hào)(即使值相同,序號(hào)也不同)。
  • 示例:按部門分區(qū),按工資降序排名(工資相同則按入職時(shí)間升序):
SELECT 
  name, 
  department, 
  salary,
  ROW_NUMBER() OVER (
    PARTITION BY department 
    ORDER BY salary DESC, hire_date ASC
  ) AS row_num
FROM employee;
  • 結(jié)果:
    namedepartmentsalaryrow_num
    李四技術(shù)部90001(同工資,入職早排前)
    王五技術(shù)部90002
    張三技術(shù)部80003
    錢七市場(chǎng)部85001
    趙六市場(chǎng)部70002

(2)RANK():帶跳號(hào)的排名

  • 功能:相同值排名相同,后續(xù)排名會(huì) "跳號(hào)"(如兩個(gè)第 1 名,下一個(gè)是第 3 名)。
  • 示例:按部門分區(qū),按工資降序排名:
SELECT 
  name, 
  department, 
  salary,
  RANK() OVER (
    PARTITION BY department 
    ORDER BY salary DESC
  ) AS rank_num
FROM employee;
  • 結(jié)果:
    namedepartmentsalaryrank_num
    李四技術(shù)部90001
    王五技術(shù)部90001(與李四并列第 1)
    張三技術(shù)部80003(跳號(hào),直接第 3)
    錢七市場(chǎng)部85001
    趙六市場(chǎng)部70002

(3)DENSE_RANK():無(wú)跳號(hào)的排名

  • 功能:相同值排名相同,后續(xù)排名不跳號(hào)(如兩個(gè)第 1 名,下一個(gè)是第 2 名)。
  • 示例:按部門分區(qū),按工資降序排名:
SELECT 
  name, 
  department, 
  salary,
  DENSE_RANK() OVER (
    PARTITION BY department 
    ORDER BY salary DESC
  ) AS dense_rank_num
FROM employee;
  • 結(jié)果:
    namedepartmentsalarydense_rank_num
    李四技術(shù)部90001
    王五技術(shù)部90001
    張三技術(shù)部80002(不跳號(hào),第 2)
    錢七市場(chǎng)部85001
    趙六市場(chǎng)部70002

2. 聚合開窗函數(shù)(聚合函數(shù) +OVER())

SUM()AVG()、COUNT()等聚合函數(shù)與OVER()結(jié)合,為每行計(jì)算所在窗口的聚合結(jié)果。

(1)全分區(qū)聚合(無(wú)ORDER BY和范圍)

  • 功能:計(jì)算整個(gè)分區(qū)的聚合值(每行的結(jié)果相同)。
  • 示例:計(jì)算每個(gè)部門的平均工資,附加到每行:
SELECT 
  name, 
  department, 
  salary,
  AVG(salary) OVER (PARTITION BY department) AS dept_avg_salary
FROM employee;
  • 結(jié)果:
    namedepartmentsalarydept_avg_salary
    張三技術(shù)部80008666.67((8000+9000+9000)/3)
    李四技術(shù)部90008666.67
    王五技術(shù)部90008666.67

(2)累計(jì)聚合(帶ORDER BY和范圍)

  • 功能:按排序順序計(jì)算 "累計(jì)" 聚合值(如累計(jì)求和、累計(jì)平均值)。
  • 示例:按部門分區(qū),按入職時(shí)間升序,計(jì)算累計(jì)工資總和:
SELECT 
  name, 
  department, 
  hire_date,
  salary,
  SUM(salary) OVER (
    PARTITION BY department 
    ORDER BY hire_date ASC
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  -- 從第一行到當(dāng)前行
  ) AS cumulative_salary
FROM employee;
  • 結(jié)果(技術(shù)部):
    namedepartmenthire_datesalarycumulative_salary
    王五技術(shù)部2018-05-1090009000(第一行,累計(jì) = 自身)
    李四技術(shù)部2019-03-20900018000(累計(jì) = 9000+9000)
    張三技術(shù)部2020-01-15800026000(累計(jì) = 9000+9000+8000)

3. 分析函數(shù)(獲取前后行數(shù)據(jù))

(1)LAG(列名, n):獲取當(dāng)前行的前 n 行數(shù)據(jù)

  • 功能:返回當(dāng)前行之前第 n 行的指定列值(默認(rèn) n=1)。
  • 示例:獲取每個(gè)部門中,當(dāng)前員工的前一位入職員工的工資:
SELECT 
  name, 
  department, 
  hire_date,
  salary,
  LAG(salary, 1) OVER (
    PARTITION BY department 
    ORDER BY hire_date ASC
  ) AS prev_emp_salary
FROM employee;
  • 結(jié)果(技術(shù)部):
    namedepartmenthire_datesalaryprev_emp_salary
    王五技術(shù)部2018-05-109000NULL(第一行,無(wú)前一行)
    李四技術(shù)部2019-03-2090009000(前一行是王五的工資)
    張三技術(shù)部2020-01-1580009000(前一行是李四的工資)

(2)LEAD(列名, n):獲取當(dāng)前行的后 n 行數(shù)據(jù)

  • 功能:返回當(dāng)前行之后第 n 行的指定列值(默認(rèn) n=1)。
  • 示例:獲取每個(gè)部門中,當(dāng)前員工的后一位入職員工的工資:
SELECT 
  name, 
  department, 
  hire_date,
  salary,
  LEAD(salary, 1) OVER (
    PARTITION BY department 
    ORDER BY hire_date ASC
  ) AS next_emp_salary
FROM employee;
  • 結(jié)果(技術(shù)部):
    namedepartmenthire_datesalarynext_emp_salary
    王五技術(shù)部2018-05-1090009000(后一行是李四的工資)
    李四技術(shù)部2019-03-2090008000(后一行是張三的工資)
    張三技術(shù)部2020-01-158000NULL(最后一行,無(wú)后一行)

五、開窗函數(shù)與GROUP BY的區(qū)別

特性GROUP BY聚合開窗函數(shù)
行處理合并分組后的行(一行 / 組)保留所有原始行
計(jì)算范圍整個(gè)分組可自定義窗口范圍(分區(qū)、行范圍)
結(jié)果列僅聚合結(jié)果 + 分組列原始列 + 開窗計(jì)算結(jié)果

六、注意事項(xiàng)

  • 排序影響ORDER BY在開窗函數(shù)中不僅影響排名,還會(huì)影響窗口范圍的界定(如累計(jì)計(jì)算)。
  • 性能考量:復(fù)雜的窗口范圍(如RANGE)可能導(dǎo)致性能下降,大表建議優(yōu)先用ROWS。
  • 數(shù)據(jù)庫(kù)支持:主流數(shù)據(jù)庫(kù)(MySQL 8.0+、PostgreSQL、SQL Server、Oracle)均支持開窗函數(shù),但部分細(xì)節(jié)可能有差異。

通過(guò)上述講解,可掌握開窗函數(shù)的核心語(yǔ)法和應(yīng)用場(chǎng)景。實(shí)際使用時(shí),需根據(jù)業(yè)務(wù)需求靈活組合PARTITION BY、ORDER BY和窗口范圍,實(shí)現(xiàn)復(fù)雜的數(shù)據(jù)分析。

到此這篇關(guān)于Mysql開窗函數(shù)的文章就介紹到這了,更多相關(guān)Mysql開窗函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mysql修改字段名和修改字段類型的實(shí)例代碼

    Mysql修改字段名和修改字段類型的實(shí)例代碼

    MySQL中如何使用SQL語(yǔ)句來(lái)修改表中某一個(gè)字段的數(shù)據(jù)類型呢,下面這篇文章主要給大家介紹了關(guān)于Mysql修改字段名和修改字段類型的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • MySQL主從同步延遲原因與解決方案

    MySQL主從同步延遲原因與解決方案

    本文主要介紹了MySQL主從同步延遲原因與解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • InnoDB的關(guān)鍵特性-插入緩存,兩次寫,自適應(yīng)hash索引詳解

    InnoDB的關(guān)鍵特性-插入緩存,兩次寫,自適應(yīng)hash索引詳解

    下面小編就為大家?guī)?lái)一篇InnoDB的關(guān)鍵特性-插入緩存,兩次寫,自適應(yīng)hash索引詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • 解決MySQL導(dǎo)入SQL時(shí)報(bào)錯(cuò)1067–Invalid default value for ‘ ’問(wèn)題

    解決MySQL導(dǎo)入SQL時(shí)報(bào)錯(cuò)1067–Invalid default value for

    文章介紹了MySQL中報(bào)錯(cuò)[ERR]1067-Invaliddefaultvaluefor‘a(chǎn)dd_date’的原因,以及如何通過(guò)修改my.ini文件禁用嚴(yán)格模式來(lái)解決這個(gè)問(wèn)題
    2026-03-03
  • MySQL總是差八個(gè)小時(shí)該如何解決

    MySQL總是差八個(gè)小時(shí)該如何解決

    最近在用mybatis時(shí)發(fā)現(xiàn),將LocalDateTime插入到數(shù)據(jù)庫(kù)時(shí)時(shí)間少了8小時(shí),下面這篇文章主要給大家介紹了關(guān)于MySQL總是差八個(gè)小時(shí)該如何解決的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • MySql中的IFNULL、NULLIF和ISNULL用法詳解

    MySql中的IFNULL、NULLIF和ISNULL用法詳解

    在做項(xiàng)目中發(fā)現(xiàn)MySql里的isnull和mssql里的有點(diǎn)不同。接下來(lái)小編通過(guò)本文給大家介紹MySql中的IFNULL、NULLIF和ISNULL用法詳解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • MySQL數(shù)據(jù)庫(kù)備份工具mylvmbackup的使用解讀

    MySQL數(shù)據(jù)庫(kù)備份工具mylvmbackup的使用解讀

    這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)備份工具mylvmbackup的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • MySQL函數(shù)之字符串函數(shù)解讀

    MySQL函數(shù)之字符串函數(shù)解讀

    MySQL提供了多種字符串函數(shù),如CONCAT、CONCAT_WS、LENGTH、CHAR_LENGTH、LEFT、RIGHT、REPLACE、SUBSTRING、TRIM、FIND_IN_SET和FORMAT,用于處理數(shù)據(jù)庫(kù)中的字符串?dāng)?shù)據(jù)
    2024-12-12
  • MySQL?to_date()日期轉(zhuǎn)換的用法及注意事項(xiàng)

    MySQL?to_date()日期轉(zhuǎn)換的用法及注意事項(xiàng)

    這篇文章主要介紹了MySQL?to_date()日期轉(zhuǎn)換的用法及注意事項(xiàng),TO_DATE()函數(shù)在不同數(shù)據(jù)庫(kù)系統(tǒng)中用于將字符串轉(zhuǎn)換為日期格式,其語(yǔ)法和參數(shù)可能有所不同,需要的朋友可以參考下
    2025-01-01
  • 利用Mysql定時(shí)+存儲(chǔ)過(guò)程創(chuàng)建臨時(shí)表統(tǒng)計(jì)數(shù)據(jù)的過(guò)程

    利用Mysql定時(shí)+存儲(chǔ)過(guò)程創(chuàng)建臨時(shí)表統(tǒng)計(jì)數(shù)據(jù)的過(guò)程

    這篇文章主要介紹了利用Mysql定時(shí)+存儲(chǔ)過(guò)程創(chuàng)建臨時(shí)表統(tǒng)計(jì)數(shù)據(jù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03

最新評(píng)論

搜索| 临泉县| 罗平县| 穆棱市| 勐海县| 会泽县| 南木林县| 偃师市| 皋兰县| 岳池县| 临澧县| 灯塔市| 九寨沟县| 沙坪坝区| 德安县| 安新县| 陇南市| 三亚市| 洞头县| 类乌齐县| 宁陕县| 郓城县| 阿尔山市| 手游| 新邵县| 洪雅县| 离岛区| 商都县| 丹阳市| 泰州市| 怀远县| 九江市| 绩溪县| 金寨县| 连州市| 正阳县| 安阳市| 绍兴市| 梁平县| 万安县| 海城市|