MySQL對window函數(shù)執(zhí)行sum函數(shù)可能出現(xiàn)的一個Bug
使用MySql的窗口函數(shù)統(tǒng)計數(shù)據(jù)時,發(fā)現(xiàn)一個小的問題,與大家一起探討下。
環(huán)境配置:
- mysql-installer-community-8.0.20.0
問題點(diǎn):在sum對window函數(shù)執(zhí)行時,如果有重復(fù)數(shù)據(jù),會直接把相同的數(shù)據(jù)相加,并不是逐步相加。
問題描述
數(shù)據(jù):在一個成績表中,有三個個字段:學(xué)生s_id,課程c_id,成績s_score。
查詢條件查詢每個課程的學(xué)生成績排名和成績匯總。
查詢結(jié)果:發(fā)現(xiàn)如果同一個課程有相同成績是,匯總成績不是累加的,而是一次全部加上去。
創(chuàng)建數(shù)據(jù)表
CREATE TABLE `Score`( `s_id` VARCHAR(20), `c_id` VARCHAR(20), `s_score` INT(3), PRIMARY KEY(`s_id`,`c_id`) )
插入數(shù)據(jù)
-- 成績表數(shù)據(jù)
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);
查詢數(shù)據(jù)
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);
查詢結(jié)果
看課程號01的統(tǒng)計結(jié)果,數(shù)據(jù)第一行的sum_v列,前兩個數(shù)據(jù)都是160,按照函數(shù)原理,數(shù)據(jù)應(yīng)該是80,160。
看課程號02的統(tǒng)計結(jié)果,發(fā)現(xiàn)結(jié)果是正確的,sum_v的第一個為90,第二個為179。
實(shí)際顯示與預(yù)期結(jié)果不一致,哪里出了問題。
| 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的數(shù)據(jù)正確,01的不正確,01與02的區(qū)別是01課程的前兩個學(xué)生成績一樣都是80。
難道是成績一樣,導(dǎo)致sum時出錯了。
為了驗證這個問題,把課程號01,學(xué)號為01的成績修改為82,然后在執(zhí)行查詢,結(jié)果如下
發(fā)現(xiàn)sum_v列顯示的為82、162,與預(yù)期結(jié)果一致。
這樣可以得出結(jié)論,在sum對window函數(shù)執(zhí)行時,如果有重復(fù)數(shù)據(jù),會直接把相同的數(shù)據(jù)相加,并不是逐步相加。
| 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驗證和對比
經(jīng)過上述驗證,Mysql在sum時確實(shí)出現(xiàn)了錯誤,不是逐步累加的。
其他平臺是否同樣存在問題,在Sqlite Expert 5.3版本驗證了下,發(fā)現(xiàn)結(jié)果一樣。
這個就奇怪了,如果是Mysql在實(shí)現(xiàn)時出錯,Sqlite出同樣錯誤的幾率小很多。
難道是sum和window函數(shù)結(jié)合使用時的特性導(dǎo)致的。歡迎一起討論和研究。
總結(jié)
到此這篇關(guān)于MySQL對window函數(shù)執(zhí)行sum函數(shù)可能出現(xiàn)的一個Bug的文章就介紹到這了,更多相關(guān)MySQL對window函數(shù)執(zhí)行sum函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Win10系統(tǒng)安裝MySQL8.0遇到的問題
這篇文章主要介紹了Win10系統(tǒng)安裝MySQL8.0遇到的問題及解決方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2019-12-12
MySQL數(shù)據(jù)庫手冊DATABASE操作與編碼(小白入門篇)
這篇文章主要介紹了MySQL數(shù)據(jù)庫手冊DATABASE操作與編碼的小白入門篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
mysql exists與not exists實(shí)例詳解
這篇文章主要介紹了mysql exists與not exists實(shí)例詳解的相關(guān)資料,鑒于 not exists 的效率往往要高于 not in , 所以一般情況下會使用前者替代后者,需要的朋友可以參考下2017-07-07
MySQL系列理解運(yùn)用union(all)與limit及exists關(guān)鍵字教程
這篇文章主要為大家介紹了MySQL系列中union(all)、limit及exists關(guān)鍵字的教程示例講解,通過本篇文章就可以理解MySQL中的這些關(guān)鍵字的概念以及實(shí)際的運(yùn)用2021-10-10

