使用MySql的窗口函數統計數據時,發現一個小的問題,與大家一起探討下。
環境配置:
- mysql-installer-community-8.0.20.0
問題點:在sum對window函數執行時,如果有重復數據,會直接把相同的數據相加,并不是逐步相加。
問題描述
數據:在一個成績表中,有三個個字段:學生s_id,課程c_id,成績s_score。
查詢條件查詢每個課程的學生成績排名和成績匯總。
查詢結果:發現如果同一個課程有相同成績是,匯總成績不是累加的,而是一次全部加上去。
創建數據表
CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
)
插入數據
-- 成績表數據
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);
查詢數據
select c_id,s_id,s_score,
first_value(s_score) over w as first_v,
last_value(s_score) over w as last_v,
sum(s_score) over w as sum_v,
max(s_score) over w as max_v,
min(s_score) over w as min_v,
count(s_id) over w as count_v,
row_number() over w as row_id,
rank() over w as rank_id,
dense_rank() over w as dense_id
from score window w as (partition by c_id order by s_score desc);
查詢結果
看課程號01的統計結果,數據第一行的sum_v列,前兩個數據都是160,按照函數原理,數據應該是80,160。
看課程號02的統計結果,發現結果是正確的,sum_v的第一個為90,第二個為179。
實際顯示與預期結果不一致,哪里出了問題。
| c_id |
s_id |
s_score |
first_v |
last_v |
sum_v |
max_v |
min_v |
count_v |
row_id |
rank_id |
dense_id |
| 01 |
01 |
80 |
80 |
80 |
160 |
80 |
80 |
2 |
1 |
1 |
1 |
| 01 |
03 |
80 |
80 |
80 |
160 |
80 |
80 |
2 |
2 |
1 |
1 |
| 01 |
05 |
76 |
80 |
76 |
236 |
80 |
76 |
3 |
3 |
3 |
2 |
| 01 |
02 |
70 |
80 |
70 |
306 |
80 |
70 |
4 |
4 |
4 |
3 |
| 01 |
04 |
50 |
80 |
50 |
356 |
80 |
50 |
5 |
5 |
5 |
4 |
| 01 |
06 |
31 |
80 |
31 |
387 |
80 |
31 |
6 |
6 |
6 |
5 |
| 02 |
01 |
90 |
90 |
90 |
90 |
90 |
90 |
1 |
1 |
1 |
1 |
| 02 |
07 |
89 |
90 |
89 |
179 |
90 |
89 |
2 |
2 |
2 |
2 |
| 02 |
05 |
87 |
90 |
87 |
266 |
90 |
87 |
3 |
3 |
3 |
3 |
| 02 |
03 |
80 |
90 |
80 |
346 |
90 |
80 |
4 |
4 |
4 |
4 |
| 02 |
02 |
60 |
90 |
60 |
406 |
90 |
60 |
5 |
5 |
5 |
5 |
| 02 |
04 |
30 |
90 |
30 |
436 |
90 |
30 |
6 |
6 |
6 |
6 |
| 03 |
01 |
99 |
99 |
99 |
99 |
99 |
99 |
1 |
1 |
1 |
1 |
| 03 |
07 |
98 |
99 |
98 |
197 |
99 |
98 |
2 |
2 |
2 |
2 |
| 03 |
02 |
80 |
99 |
80 |
357 |
99 |
80 |
4 |
3 |
3 |
3 |
| 03 |
03 |
80 |
99 |
80 |
357 |
99 |
80 |
4 |
4 |
3 |
3 |
| 03 |
06 |
34 |
99 |
34 |
391 |
99 |
34 |
5 |
5 |
5 |
4 |
| 03 |
04 |
20 |
99 |
20 |
411 |
99 |
20 |
6 |
6 |
6 |
5 |
思考驗證
課程號02的數據正確,01的不正確,01與02的區別是01課程的前兩個學生成績一樣都是80。
難道是成績一樣,導致sum時出錯了。
為了驗證這個問題,把課程號01,學號為01的成績修改為82,然后在執行查詢,結果如下
發現sum_v列顯示的為82、162,與預期結果一致。
這樣可以得出結論,在sum對window函數執行時,如果有重復數據,會直接把相同的數據相加,并不是逐步相加。
| c_id |
s_id |
s_score |
first_v |
last_v |
sum_v |
max_v |
min_v |
count_v |
row_id |
rank_id |
dense_id |
| 01 |
01 |
80 |
80 |
82 |
82 |
82 |
82 |
2 |
1 |
1 |
1 |
| 01 |
03 |
80 |
80 |
80 |
162 |
82 |
80 |
2 |
2 |
1 |
1 |
| 01 |
05 |
76 |
80 |
76 |
236 |
82 |
76 |
3 |
3 |
3 |
2 |
| 01 |
02 |
70 |
80 |
70 |
306 |
82 |
70 |
4 |
4 |
4 |
3 |
| 01 |
04 |
50 |
80 |
50 |
356 |
82 |
50 |
5 |
5 |
5 |
4 |
| 01 |
06 |
31 |
80 |
31 |
387 |
82 |
31 |
6 |
6 |
6 |
5 |
| 02 |
01 |
90 |
90 |
90 |
90 |
90 |
90 |
1 |
1 |
1 |
1 |
| 02 |
07 |
89 |
90 |
89 |
179 |
90 |
89 |
2 |
2 |
2 |
2 |
| 02 |
05 |
87 |
90 |
87 |
266 |
90 |
87 |
3 |
3 |
3 |
3 |
| 02 |
03 |
80 |
90 |
80 |
346 |
90 |
80 |
4 |
4 |
4 |
4 |
| 02 |
02 |
60 |
90 |
60 |
406 |
90 |
60 |
5 |
5 |
5 |
5 |
| 02 |
04 |
30 |
90 |
30 |
436 |
90 |
30 |
6 |
6 |
6 |
6 |
| 03 |
01 |
99 |
99 |
99 |
99 |
99 |
99 |
1 |
1 |
1 |
1 |
| 03 |
07 |
98 |
99 |
98 |
197 |
99 |
98 |
2 |
2 |
2 |
2 |
| 03 |
02 |
80 |
99 |
80 |
357 |
99 |
80 |
4 |
3 |
3 |
3 |
| 03 |
03 |
80 |
99 |
80 |
357 |
99 |
80 |
4 |
4 |
3 |
3 |
| 03 |
06 |
34 |
99 |
34 |
391 |
99 |
34 |
5 |
5 |
5 |
4 |
| 03 |
04 |
20 |
99 |
20 |
411 |
99 |
20 |
6 |
6 |
6 |
5 |
其他Sql驗證和對比
經過上述驗證,Mysql在sum時確實出現了錯誤,不是逐步累加的。
其他平臺是否同樣存在問題,在Sqlite Expert 5.3版本驗證了下,發現結果一樣。
這個就奇怪了,如果是Mysql在實現時出錯,Sqlite出同樣錯誤的幾率小很多。
難道是sum和window函數結合使用時的特性導致的。歡迎一起討論和研究。
總結
到此這篇關于MySQL對window函數執行sum函數可能出現的一個Bug的文章就介紹到這了,更多相關MySQL對window函數執行sum函數內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Mysql臨時表及分區表區別詳解
- MySQL最佳實踐之分區表基本類型
- MySQL分區表的基本入門教程
- MySQL優化之分區表
- 解決mysql刪除用戶 bug的問題
- MySQL關于exists的一個bug
- CentOS 安裝 PHP5.5+Redis+XDebug+Nginx+MySQL全紀錄
- 關于MySQL分區表的一個性能BUG