1. 程式人生 > 資料庫 >Mysql8的分組排序

Mysql8的分組排序

Mysql8之前Group By支援分組排序

如: 

select * 
from (
select * from user_position order by userId,time desc
) as u 
group by u.userId  

或如:

select * 
from  user_position 
group by userId  desc

  

會取每組時間最新的一條,官方給出解釋:

預設情況下GROUP BY隱式排序(即,缺少GROUP BY列的ASC或DESC指示符)。但是,不推薦依賴於隱式GROUP BY排序(即,在沒有ASC或DESC指示符的情況下排序)或GROUP BY的顯式排序(即,通過對GROUP BY列使用顯式ASC或DESC指示符)。要生成給定的排序 ORDER,請提供ORDER BY子句。 

但是在Mysql8之後不再支援這兩種排序

具體原因:見 

替代方式:

1、通過limit關鍵詞,如:

select * 
from (
select * from user_position order by userId,time desc limit 9999
) as u 
group by u.userId  

使用limit之後,在group by 之前會保持排序

弊端:limit的數量有時候很難清楚

2、使用 in的方式

          SELECT
			*
		FROM
			message_audit cma LEFT JOIN message cm ON cm.id = cma.message_id
		WHERE
			cma.id IN ( SELECT max( id ) FROM message_audit GROUP BY message_id )

 弊端:in的id數量過大的話,效率極其低下,滿足不了要求

3、使用視窗函式(分析函式) ROW_NUMBER() OVER()

在mysql8.0之後,開始支援視窗函式,我們可是使用視窗函式來完成分組排序,並且更加方便,如:

         WITH tb AS (SELECT
			cm.msg_title,
			cma.message_id,
			cma.id,
			cma.create_time,
			cma.audit_status,
			cma.audit_reason,
			cma.audit_time,
			cma.external_audit_status,
			cma.external_audit_reason,
			ROW_NUMBER () OVER ( PARTITION BY cma.message_id ORDER BY cma.create_time DESC ) AS RN 
		FROM
			message_audit cma LEFT JOIN message cm ON cm.id = cma.message_id
		WHERE
			cma.sys_audit_status = 1
	) SELECT * FROM tb  WHERE RN = 1

			 

  解釋: ROW_NUMBER () OVER ( PARTITION BY cma.message_id ORDER BY cma.create_time DESC ) AS RN,根據 message_id來分組,根據 create_time來排序

獲取的結果標記行號RN,最好根據RN=1來獲取最新的記錄,當然我們也可以獲取最新的兩條、三條記錄,處理結果比第二種方法效果更好