用慣了hive的row_number,在Mysql中想要使用分組排序的功能時,卻發現不那么簡單 —— 貌似不能一個函數解決。
有時候又特別需要使用,怎么辦呢?不慌,這也還是有方法的。
首先建立數據表:
create table t_variable ( name_people VARCHAR(255) NOT NULL comment '姓名', grade VARCHAR(255) NOT NULL comment '年級', course VARCHAR(255) NOT NULL comment '科目', score VARCHAR(255) NOT NULL comment '分數' )ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='test_變量'; insert into t_variable(name_people, grade, course, score) values('花滿樓',5,'數學',86); insert into t_variable(name_people, grade, course, score) values('陸小鳳',5,'數學',94); insert into t_variable(name_people, grade, course, score) values('西門吹雪',5,'數學',90); insert into t_variable(name_people, grade, course, score) values('花滿樓',5,'語文',97); insert into t_variable(name_people, grade, course, score) values('陸小鳳',5,'語文',95); insert into t_variable(name_people, grade, course, score) values('西門吹雪',5,'語文',89); insert into t_variable(name_people, grade, course, score) values('花滿樓',5,'科學',93); insert into t_variable(name_people, grade, course, score) values('陸小鳳',5,'科學',96); insert into t_variable(name_people, grade, course, score) values('西門吹雪',5,'科學',94);
那么,分組排序:
方法一:使用變量@ —— 還可以選擇排名在第幾的人。
select name_people, course, score, @ss, @tt, if(@ss=course, @tt:=@tt+1, @tt:=1) as rk, @ss:=course as a_course from ( select * from t_variable order by course, score desc # 先按分組字段和排序字段進行整體排序,這樣相同選擇字段的記錄就會前后排列 ) as t1 cross join #直接笛卡爾積 ( select @ss:='', #初始值 @tt:=0 ) as t2;
方法二:group_concat —— 同一分組內的值先連接,再選取;#[Err] 1140 - In aggregated query without GROUP BY, expression #1,使用group_concat必須用group by
select course, group_concat(score order by score desc) as sc #連接的是排序字段 from t_variable group by course #分組字段
可使用 substring_index 進行選擇第幾個:
select course, substring_index(group_concat(score order by score desc),',',1) as sc from t_variable group by course
當然,如果要知道是哪條記錄在排名第一的位置,需要用這個結果與原始表join選擇一下。
方法三:通過join查詢實現
select * from ( select a.course, a.score, count(*) as sc from t_variable as a left join t_variable as b on a.course=b.course #本來的分組字段 and a.score<=b.score #本來的排序字段 group by course, #此時才對以上結果進行分組 score ) as c where c.sc=1;
這個稍微復雜一點,是通過join之后,進行篩選,再對篩選結果分組計數得到,只需要看個中間表即可 —— 因為最大值小於等於的值只有它本身,也就是對小於等於的記錄進行計數count時,值會為1,其他非最大值都會大於1:
select a.course, a.score, count(*) as sc from t_variable as a left join t_variable as b on a.course=b.course and a.score<=b.score group by course, score;
附:substring_index —— SUBSTRING_INDEX(str,delim,count),用於獲取子字符串
-- str:待處理字符串
-- delim:分隔符
-- count:計數值
若count是正數,則從左往右數,第count個分隔符左邊的字符串
若count是負數,則從右往左數,第count個分隔符右邊的字符串
select substring_index('烽火台、長城、頤和園、北海','、',1) select substring_index('烽火台、長城、頤和園、北海','、',3) select substring_index('烽火台、長城、頤和園、北海','、',-2) select substring_index(substring_index('烽火台、長城、頤和園、北海','、',2),'、','-1') #如果選中間的子字符串,可以嵌套
#
參考:
https://blog.csdn.net/m0_37797991/article/details/80511855