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

MySQL窗口函數(shù) OVER()全解析

 更新時(shí)間:2025年12月31日 11:36:59   作者:代碼or搬磚  
MySQL窗口函數(shù)是用于在查詢結(jié)果集中執(zhí)行計(jì)算的強(qiáng)大工具,它們可以對(duì)一組行(窗口)進(jìn)行計(jì)算,并為每一行返回一個(gè)值,而不會(huì)減少行數(shù),本文給大家介紹MySQL窗口函數(shù) OVER()的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧

一、窗口函數(shù)概述

1. 什么是窗口函數(shù)?

窗口函數(shù)Window Function)是對(duì)一組行(稱為"窗口")執(zhí)行計(jì)算,并為每一行返回一個(gè)值的函數(shù)。與聚合函數(shù)不同,窗口函數(shù)不減少行數(shù)。

2. 窗口函數(shù) vs 聚合函數(shù)

特性窗口函數(shù)聚合函數(shù)
返回行數(shù)與輸入行數(shù)相同通常減少行數(shù)(GROUP BY)
分組效果保留所有行,添加計(jì)算結(jié)果每組返回一行
語(yǔ)法位置SELECT 子句中SELECT 或 HAVING 子句中
典型函數(shù)ROW_NUMBER(), RANK(), SUM() OVER()SUM(), COUNT(), AVG()

3. 基本語(yǔ)法結(jié)構(gòu)

窗口函數(shù)([參數(shù)]) OVER (
  [PARTITION BY <分組列>] 
  [ORDER BY <排序列 ASC/DESC>]
  [ROWS BETWEEN 開(kāi)始行 AND 結(jié)束行]
)
  • OVER() 里面不能直接放 GROUP BY!可以放PARTITION BY
  • PARTITION BY 子句用于指定分組列,關(guān)鍵字:PARTITION BY 。
  • ORDER BY 子句用于指定排序列,關(guān)鍵字ORDER BY 。
  • ROWS BETWEEN 子句用于指定窗口的范圍,關(guān)鍵字ROWS BETWEEN 即[開(kāi)始行]、[結(jié)束行]

其中,ROWS BETWEEN 子句在實(shí)際中可能用得相對(duì)少一些,因此有部分參考資料的語(yǔ)法描述省略了ROWS BETWEEN 子句,主要側(cè)重于PARTITION BY分組與ORDER BY排序:

二、窗口函數(shù)核心組成部分

1. PARTITION BY - 分區(qū)子句

將數(shù)據(jù)劃分為多個(gè)分區(qū),在每個(gè)分區(qū)內(nèi)獨(dú)立計(jì)算。

-- 創(chuàng)建測(cè)試數(shù)據(jù)
CREATE TABLE sales (
    id INT PRIMARY KEY AUTO_INCREMENT,
    salesperson VARCHAR(50),
    region VARCHAR(50),
    sale_date DATE,
    amount DECIMAL(10, 2)
);
INSERT INTO sales (salesperson, region, sale_date, amount) VALUES
('張三', '北京', '2024-01-01', 1000.00),
('張三', '北京', '2024-01-02', 1500.00),
('李四', '上海', '2024-01-01', 2000.00),
('李四', '上海', '2024-01-02', 2500.00),
('王五', '北京', '2024-01-01', 1200.00),
('王五', '北京', '2024-01-03', 1800.00),
('趙六', '廣州', '2024-01-02', 2200.00);
-- 按銷(xiāo)售員分區(qū)計(jì)算
SELECT 
    salesperson,
    sale_date,
    amount,
    -- 每個(gè)銷(xiāo)售員的銷(xiāo)售總額
    SUM(amount) OVER (PARTITION BY salesperson) AS total_by_person,
    -- 每個(gè)地區(qū)的銷(xiāo)售總額
    SUM(amount) OVER (PARTITION BY region) AS total_by_region,
    -- 不分區(qū)(全局總額)
    SUM(amount) OVER () AS grand_total
FROM sales
ORDER BY salesperson, sale_date;

輸出結(jié)果:

salesperson | sale_date  | amount | total_by_person | total_by_region | grand_total
------------|------------|--------|-----------------|-----------------|------------
張三        | 2024-01-01 | 1000.00| 2500.00         | 5500.00         | 12200.00
張三        | 2024-01-02 | 1500.00| 2500.00         | 5500.00         | 12200.00
李四        | 2024-01-01 | 2000.00| 4500.00         | 4500.00         | 12200.00
李四        | 2024-01-02 | 2500.00| 4500.00         | 4500.00         | 12200.00
王五        | 2024-01-01 | 1200.00| 3000.00         | 5500.00         | 12200.00
王五        | 2024-01-03 | 1800.00| 3000.00         | 5500.00         | 12200.00
趙六        | 2024-01-02 | 2200.00| 2200.00         | 2200.00         | 12200.00

2. ORDER BY - 排序子句

在分區(qū)內(nèi)對(duì)行進(jìn)行排序,影響排名函數(shù)和累計(jì)計(jì)算。

SELECT 
    salesperson,
    sale_date,
    amount,
    -- 按金額排序(分區(qū)內(nèi))
    ROW_NUMBER() OVER (PARTITION BY salesperson ORDER BY amount DESC) AS rn,
    -- 累計(jì)金額(分區(qū)內(nèi)按日期排序)
    SUM(amount) OVER (PARTITION BY salesperson ORDER BY sale_date) AS running_total,
    -- 移動(dòng)平均值(最近3行的平均值)
    AVG(amount) OVER (PARTITION BY salesperson ORDER BY sale_date 
         ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3
FROM sales
ORDER BY salesperson, sale_date;

3.聚合窗口函數(shù)

許多窗口函數(shù)的教程,通常將常用的窗口函數(shù)分為兩大類:聚合窗口函數(shù)專用窗口函數(shù)。聚合窗口函數(shù)的函數(shù)名與普通常用聚合函數(shù)一致,功能也一致。從使用的角度來(lái)講,與普通聚合函數(shù)的區(qū)別在于提供了窗口函數(shù)的專屬子句,來(lái)使得數(shù)據(jù)的分析與獲取更簡(jiǎn)便。主要有如下幾個(gè):

函數(shù)名作用
SUM對(duì)指定列的數(shù)值求和
AVG計(jì)算指定列的平均值
COUNT統(tǒng)計(jì)記錄/非空值數(shù)量
MAX找出指定列的最大值
MIN找出指定列的最小值

4.專用窗口函數(shù)

常見(jiàn)的專用窗口函數(shù)

函數(shù)名分類說(shuō)明
RANK排序函數(shù)類似于排名,并列的結(jié)果序號(hào)可以重復(fù),序號(hào)不連續(xù)(如:1,2,2,4)
DENSE_RANK排序函數(shù)類似于排名,并列的結(jié)果序號(hào)可以重復(fù),序號(hào)連續(xù)(如:1,2,2,3)
ROW_NUMBER排序函數(shù)對(duì)分組下的所有結(jié)果排序,基于分組分配唯一連續(xù)的行號(hào)(如:1,2,3,4)
PERCENT_RANK分布函數(shù)每行按公式 (rank-1) / (rows-1) 計(jì)算,結(jié)果為0~1的百分比值
CUME_DIST分布函數(shù)分組內(nèi)小于等于當(dāng)前rank值的行數(shù) ÷ 分組內(nèi)總行數(shù),結(jié)果為0~1的百分比值

5. ROWS BETWEEN - 窗口幀子句

定義窗口函數(shù)的計(jì)算范圍。

-- 各種窗口幀的示例
SELECT 
    salesperson,
    sale_date,
    amount,
    -- 默認(rèn):分區(qū)內(nèi)所有行
    SUM(amount) OVER (PARTITION BY salesperson) AS total_all,
    -- ROWS模式:物理行
    SUM(amount) OVER (
        PARTITION BY salesperson 
        ORDER BY sale_date
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cumulative_rows,
    -- RANGE模式:邏輯值范圍(相同值的行視為同一幀)
    SUM(amount) OVER (
        PARTITION BY salesperson 
        ORDER BY sale_date
        RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cumulative_range,
    -- 滑動(dòng)窗口:當(dāng)前行及前2行
    SUM(amount) OVER (
        PARTITION BY salesperson 
        ORDER BY sale_date
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) AS sum_last_3,
    -- 前后各一行
    SUM(amount) OVER (
        PARTITION BY salesperson 
        ORDER BY sale_date
        ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
    ) AS sum_neighbors
FROM sales
ORDER BY salesperson, sale_date;

三、窗口函數(shù)分類詳解

1. 序號(hào)函數(shù)(Ranking Functions)

-- 創(chuàng)建測(cè)試數(shù)據(jù)
CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    department VARCHAR(50),
    salary DECIMAL(10, 2)
);
INSERT INTO employees (name, department, salary) VALUES
('張三', '技術(shù)部', 8000.00),
('李四', '技術(shù)部', 9000.00),
('王五', '技術(shù)部', 9500.00),
('趙六', '技術(shù)部', 9000.00),
('錢(qián)七', '銷(xiāo)售部', 7000.00),
('孫八', '銷(xiāo)售部', 8500.00),
('周九', '銷(xiāo)售部', 8500.00),
('吳十', '銷(xiāo)售部', 7500.00);
-- 1. ROW_NUMBER():連續(xù)不重復(fù)的序號(hào)
SELECT 
    name,
    department,
    salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
FROM employees;
-- 2. RANK():有間隔的排名(相同值排名相同,下一個(gè)排名跳躍)
SELECT 
    name,
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank_num
FROM employees;
-- 3. DENSE_RANK():無(wú)間隔的排名(相同值排名相同,下一個(gè)排名連續(xù))
SELECT 
    name,
    department,
    salary,
    DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dense_rank_num
FROM employees;
-- 4. NTILE(n):將數(shù)據(jù)分為n組
SELECT 
    name,
    department,
    salary,
    NTILE(4) OVER (PARTITION BY department ORDER BY salary DESC) AS quartile
FROM employees;

輸出對(duì)比:

部門(mén)   | 姓名 | 薪資   | ROW_NUMBER | RANK | DENSE_RANK | NTILE(4)
------|------|--------|------------|------|------------|---------
技術(shù)部 | 王五 | 9500   | 1          | 1    | 1          | 1
技術(shù)部 | 李四 | 9000   | 2          | 2    | 2          | 1
技術(shù)部 | 趙六 | 9000   | 3          | 2    | 2          | 2
技術(shù)部 | 張三 | 8000   | 4          | 4    | 3          | 2
銷(xiāo)售部 | 孫八 | 8500   | 1          | 1    | 1          | 1
銷(xiāo)售部 | 周九 | 8500   | 2          | 1    | 1          | 1
銷(xiāo)售部 | 吳十 | 7500   | 3          | 3    | 2          | 2
銷(xiāo)售部 | 錢(qián)七 | 7000   | 4          | 4    | 3          | 2

2. 分布函數(shù)(Distribution Functions)

-- 5. PERCENT_RANK():百分比排名 (rank - 1) / (total_rows - 1)
SELECT 
    name,
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary) AS rank_num,
    PERCENT_RANK() OVER (PARTITION BY department ORDER BY salary) AS percent_rank
FROM employees;
-- 6. CUME_DIST():累計(jì)分布(小于等于當(dāng)前值的行數(shù) / 總行數(shù))
SELECT 
    name,
    department,
    salary,
    CUME_DIST() OVER (PARTITION BY department ORDER BY salary) AS cume_dist
FROM employees;
-- 7. PERCENTILE_CONT():連續(xù)百分位數(shù)(需要MySQL 8.0.2+)
SELECT 
    department,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) 
        OVER (PARTITION BY department) AS median_salary
FROM employees
GROUP BY department, salary;
-- 8. PERCENTILE_DISC():離散百分位數(shù)
SELECT 
    department,
    PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY salary) 
        OVER (PARTITION BY department) AS median_salary
FROM employees
GROUP BY department, salary;

3. 前后值函數(shù)(Value Functions)

-- 9. LAG(column, n, default):獲取前n行的值
SELECT 
    name,
    department,
    salary,
    LAG(salary, 1, 0) OVER (PARTITION BY department ORDER BY salary) AS prev_salary,
    salary - LAG(salary, 1, 0) OVER (PARTITION BY department ORDER BY salary) AS salary_diff
FROM employees;
-- 10. LEAD(column, n, default):獲取后n行的值
SELECT 
    name,
    department,
    sale_date,
    amount,
    LEAD(amount, 1, 0) OVER (PARTITION BY salesperson ORDER BY sale_date) AS next_amount,
    LEAD(sale_date, 1, NULL) OVER (PARTITION BY salesperson ORDER BY sale_date) AS next_date
FROM sales;
-- 11. FIRST_VALUE(column):窗口內(nèi)第一個(gè)值
SELECT 
    name,
    department,
    salary,
    FIRST_VALUE(salary) OVER (
        PARTITION BY department 
        ORDER BY salary 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS lowest_salary,
    salary - FIRST_VALUE(salary) OVER (
        PARTITION BY department 
        ORDER BY salary 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS diff_from_lowest
FROM employees;
-- 12. LAST_VALUE(column):窗口內(nèi)最后一個(gè)值(注意默認(rèn)窗口幀?。?
SELECT 
    name,
    department,
    salary,
    -- 錯(cuò)誤用法:默認(rèn)窗口幀是 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary) AS wrong_last_value,
    -- 正確用法:指定完整的窗口幀
    LAST_VALUE(salary) OVER (
        PARTITION BY department 
        ORDER BY salary 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS correct_last_value,
    -- 或者使用NTH_VALUE
    NTH_VALUE(salary, 1) OVER (
        PARTITION BY department 
        ORDER BY salary 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS first_salary,
    NTH_VALUE(salary, 2) OVER (
        PARTITION BY department 
        ORDER BY salary 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS second_salary
FROM employees;

4. 聚合函數(shù)作為窗口函數(shù)

-- 所有聚合函數(shù)都可以作為窗口函數(shù)使用
SELECT 
    salesperson,
    region,
    sale_date,
    amount,
    -- 聚合函數(shù)
    COUNT(*) OVER (PARTITION BY salesperson) AS total_transactions,
    SUM(amount) OVER (PARTITION BY salesperson) AS total_amount,
    AVG(amount) OVER (PARTITION BY salesperson) AS avg_amount,
    MAX(amount) OVER (PARTITION BY salesperson) AS max_amount,
    MIN(amount) OVER (PARTITION BY salesperson) AS min_amount,
    -- 標(biāo)準(zhǔn)差和方差(MySQL 8.0+)
    STDDEV(amount) OVER (PARTITION BY salesperson) AS std_amount,
    VARIANCE(amount) OVER (PARTITION BY salesperson) AS var_amount,
    -- 累計(jì)聚合
    SUM(amount) OVER (
        PARTITION BY salesperson 
        ORDER BY sale_date
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS running_total,
    -- 移動(dòng)平均
    AVG(amount) OVER (
        PARTITION BY salesperson 
        ORDER BY sale_date
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) AS moving_avg_3,
    -- 百分比
    amount * 100.0 / SUM(amount) OVER (PARTITION BY salesperson) AS percentage
FROM sales
ORDER BY salesperson, sale_date;

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

相關(guān)文章

  • You must SET PASSWORD before executing this statement的解決方法

    You must SET PASSWORD before execut

    今天在MySql5.6操作時(shí)報(bào)錯(cuò):You must SET PASSWORD before executing this statement解決方法,需要的朋友可以參考下
    2013-06-06
  • Mysql配置主從復(fù)制-GTID模式詳解

    Mysql配置主從復(fù)制-GTID模式詳解

    這篇文章主要介紹了Mysql配置主從復(fù)制-GTID模式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • MySQL5.x版本亂碼問(wèn)題解決方案

    MySQL5.x版本亂碼問(wèn)題解決方案

    這篇文章主要介紹了MySQL5.x版本亂碼問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 使用mysqldump實(shí)現(xiàn)mysql備份

    使用mysqldump實(shí)現(xiàn)mysql備份

    mysqldump客戶端可用來(lái)轉(zhuǎn)儲(chǔ)數(shù)據(jù)庫(kù)或搜集數(shù)據(jù)庫(kù)進(jìn)行備份或?qū)?shù)據(jù)轉(zhuǎn)移到另一個(gè)SQL服務(wù)器(不一定是一個(gè)MySQL服務(wù)器)。今天我們就來(lái)詳細(xì)探討下mysqldump的使用方法
    2016-11-11
  • MySQL數(shù)據(jù)庫(kù)優(yōu)化技術(shù)之配置技巧總結(jié)

    MySQL數(shù)據(jù)庫(kù)優(yōu)化技術(shù)之配置技巧總結(jié)

    這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)優(yōu)化技術(shù)之配置技巧,較為詳細(xì)的總結(jié)分析了MySQL進(jìn)行硬件級(jí)軟件優(yōu)化的相關(guān)方法與注意事項(xiàng),需要的朋友可以參考下
    2016-07-07
  • 解決MySQL Sending data導(dǎo)致查詢很慢問(wèn)題的方法與思路

    解決MySQL Sending data導(dǎo)致查詢很慢問(wèn)題的方法與思路

    這篇文章主要介紹了解決MySQL Sending data導(dǎo)致查詢很慢問(wèn)題的方法與思路,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 詳解MySQL的數(shù)據(jù)行和行溢出機(jī)制

    詳解MySQL的數(shù)據(jù)行和行溢出機(jī)制

    在前面的文章中,白日夢(mèng)曾不止一次的提及到:InnoDB從磁盤(pán)中讀取數(shù)據(jù)的最小單位是數(shù)據(jù)頁(yè)。 而你想得到的id = xxx的數(shù)據(jù),就是這個(gè)數(shù)據(jù)頁(yè)眾多行中的一行。 這篇文章我們就一起來(lái)看一下數(shù)據(jù)行設(shè)計(jì)的多么巧妙。
    2020-11-11
  • MySQL?5.7中NULL與‘?‘空字符值的多維度分析(詳解)

    MySQL?5.7中NULL與‘?‘空字符值的多維度分析(詳解)

    在數(shù)據(jù)庫(kù)設(shè)計(jì)和開(kāi)發(fā)過(guò)程中,正確理解和使用NULL值對(duì)于確保數(shù)據(jù)質(zhì)量和查詢效率至關(guān)重要,本文將從多個(gè)維度對(duì)NULL值進(jìn)行深入分析,并與空字符串''以及其他控制進(jìn)行對(duì)比,旨在為讀者提供一個(gè)全面而清晰的理解,感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • InnoDB中不同SQL語(yǔ)句設(shè)置鎖的情況詳解

    InnoDB中不同SQL語(yǔ)句設(shè)置鎖的情況詳解

    這篇文章主要介紹了InnoDB中不同SQL語(yǔ)句設(shè)置鎖的情況詳解,在Mysql中,鎖定讀、更新、刪除操作通常會(huì)對(duì)SQL語(yǔ)句處理過(guò)程中掃描到的每條索引記錄設(shè)置記錄鎖,需要的朋友可以參考下
    2024-01-01
  • 詳解Mysql通訊協(xié)議

    詳解Mysql通訊協(xié)議

    這篇文章對(duì)Mysql的通訊協(xié)議做了詳細(xì)介紹和說(shuō)明,希望我們整理的內(nèi)容對(duì)你有用,一起學(xué)習(xí)下吧。
    2017-12-12

最新評(píng)論

仙桃市| 鄯善县| 林甸县| 鹿邑县| 永清县| 凤山县| 枣阳市| 云龙县| 固阳县| 东莞市| 庆元县| 宁武县| 响水县| 肥乡县| 突泉县| 交口县| 焉耆| 滨州市| 樟树市| 花莲市| 温州市| 丹寨县| 涿鹿县| 萨嘎县| 金秀| 巴楚县| 安溪县| 临漳县| 营山县| 墨竹工卡县| 昌吉市| 普格县| 汨罗市| 阳信县| 高雄县| 瓦房店市| 将乐县| 屏山县| 正蓝旗| 武隆县| 和静县|