Mysql分組排序的三種方法以及substring_index


用慣了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

https://www.cnblogs.com/mqxs/p/7380933.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM