目錄
一、感受一下分組與窗口函數的區別
二、滑動窗口(子窗口)大小的確認
2.1 分組函數下order by使用
?2.2 窗口子句
2.3 執行流程
三、函數使用
窗口函數需要mysql的版本大于等于8才行,可以先檢查一下自己的mysql版本是多少
select version();
準備一下表數據
drop table if exists student;
create table student
(cid varchar(50),sname varchar(50),course varchar(50),score int
) character set utf8mb4;-- 插入兩個班級的學生數據(每個學生包含4門課程成績)
INSERT INTO student (cid, sname, course, score)
VALUES
-- 班級01
('01', '張三', '語文', 85),
('01', '張三', '數學', 92),
('01', '張三', '英語', 78),
('01', '張三', '物理', 88),
('01', '李四', '語文', 76),
('01', '李四', '數學', 88),
('01', '李四', '英語', 95),
('01', '李四', '化學', 90),
('01', '王五', '語文', 65),
('01', '王五', '數學', 73),
('01', '王五', '英語', 82),
('01', '王五', '生物', 77), -- 班級02
('02', '趙六', '語文', 90),
('02', '趙六', '數學', 67),
('02', '趙六', '英語', 88),
('02', '趙六', '地理', 85),
('02', '陳七', '語文', 72),
('02', '陳七', '數學', 85),
('02', '陳七', '英語', 91),
('02', '陳七', '歷史', 89),
('02', '周八', '語文', 68),
('02', '周八', '數學', 79),
('02', '周八', '英語', 84),
('02', '周八', '政治', 83);
一、感受一下分組與窗口函數的區別
假設現在有一個需求需要統計每個學生的各科總成績,我們分別使用分組group by 和窗口函數 partition by 來試一下
先來看看group by
select cid, sname, sum(score)
from student
group by sname;
?這里是以每個學生的名字來分組的,顯然這里只有六個學生,那么就只會有六行數據
接下來我們看看 partition by的使用
select *,sum(score) over (partition by sname)
from student;
從行來看:可以很明顯的感受到,分組group by是先分組在把數據進行壓縮,但是窗口函數是保留了并沒有對行數進行壓縮
從列來看:也是發現一個mysql5.7和mysql8的區別,因為我本機是5.7,在云服務器上面用了mysql8,今天驚奇的發現mysql8,不是分組列,不能被展示,意思就是我只能展示兩列,一列是sname(分組列),聚合函數一列
也就是說group by生成的表與原有的表行數和列數都不相同
?
二、滑動窗口(子窗口)大小的確認
2.1 分組函數下order by使用
先說結論,排序只會在當前窗口內進行排序
假設現在有一個需求,需要查詢每個同學的各科成績為降序排列
select sname, course, score,
row_number() over (partition by sname order by score desc)
from student;
?2.2 窗口子句
窗口子句:控制每一行在可以滑動的子窗口的窗口的大小 |
起始行:N preceding/unbounded preceding |
當前行:current row |
終止行:N followding/unbounded preceding |
舉例:rows between 上邊界 and 下邊界
#從之前的所有行到當前行
rows between unbounded preceding and current row
#從前面的兩行到當前行
rows between 2 preceding and current row
#從當前的所有行到之后的所有行
rows between current row and unbounded following
#從當前行到后面一行
rows between current row and 1 following
注意:
如果排序子句后面缺少窗口子句:?窗口規范默認是:#從之前的所有行到當前行
rows between unbounded preceding and current row
排序子句和窗口子句都缺少:窗口規范就是:分組的窗口大小
rows between unbounded preceding and unbounded following
2.3 執行流程
- 先通過partition by 和order by 定義整個分組的大窗口
- 通過orws 子句來定義每一行數據的滑動窗口
- 對每行的小窗口內的數據執行并生成新的列
三、函數使用
3.1 排序類
在 SQL 中,rank(),dense_rank(),row_number?是窗口函數,它們的 ??排序依據?? 完全由 over子句中的 order by?字段決定的!!!
函數 | 重復值處理邏輯 | 示例(分數為 90 的兩人) |
---|---|---|
??ROW_NUMBER()?? | 為每行分配唯一序號,即使值相同也按順序編號。 | 90 → 1, 90 → 2 |
??RANK()?? | 相同值分配相同排名,后續排名跳躍。 | 90 → 1, 90 → 1 ?→ 下一行為?3 |
??DENSE_RANK()?? | 相同值分配相同排名,后續排名連續。 | 90 → 1, 90 → 1 ?→ 下一行為?2 |