實踐 相同組獲取第一條資料的幾種SQL實現

2021-10-13 08:45:42 字數 4288 閱讀 2792

利用group by後聚合函式,比如:max, min等

此種方式簡單粗暴,存在乙個隱藏問題,就是非分組列獲取值不一定是同一行的資料,比如:這裡的workout_time

此種方式適用於mariadb,如果想適用於mysql需要修改any_value(wr.workout_date),存在非分組列相同問題

select       

h.id as

'hospital_id'

, h.name as

'hospital_name'

, p.id as

'patient_id'

, p.name as

'patient_name'

,

ed.game_id, g.name as

'game_name'

,max

(ed.score)

as'game_score'

, wr.workout_date as

'workout_time'

from

t_p p,

t_w_r wr,

t_e_d ed,

t_h h,

t_g g

where

p.name =

'kenny'

and p.id = wr.patient_id

and wr.id = ed.workout_id

and p.hospital_id = h.id

and ed.game_id = g.id

group

by p.id, p.name, ed.game_id, workout_time

order

by game_id, game_score desc

;

row_number() over(partition by [fields] order by [fields]) as 『row_num』

此種方式適用於mariadb,不適用在低版本mysql,聽說8.0以上支援

select

*from

(select row_number(

)over

(partition

by p.id, p.name, ed.game_id order

by game_id, game_score desc)as

'row_num'

, h.id as

'hospital_id'

, h.name as

'hospital_name'

, p.id as

'patient_id'

, p.name as

'patient_name'

, p.gender,

ed.game_id, g.name as

'game_name'

, g.limb, ed.score as

'game_score'

, wr.workout_date as

'workout_time'

from

t_p p,

t_w_r wr,

t_e_d ed,

t_h h,

t_g g

where

-- p.name = 'kenny' and

ed.game_id =

28and

workout_date >=

'2019-09-11'

and p.id = wr.patient_id

and wr.id = ed.workout_id

and p.hospital_id = h.id

and ed.game_id = g.id

order

by game_id, game_score desc

) twhere row_num =

1

set @row_number = 0; select @row_number:=if(@pre_game_id = game_id, @row_number + 1, 1) as 'row_num', @pre_game_id:=game_id as 'game_id2', t.*from where row_num = 1

此種方式適用於mysql,但是,在mariadb中使用需要解決乙個問題,明明子查詢已經排序再設定行號,但是就是設定行號的時候不是按照排序後的,可以說行號設定在排序前進行了,因此出來的結果同乙個分組同時存在幾條row_num = 1的情況

經試驗後,確定mariadb需要加入group by方可分組排序後才能正確新增行號

set @row_number = 0;另外,這句不加,如果在client第一次執行會出現行號都是1的情況

經試驗後,是因為@pre_game_id沒有初始值,而@row_number可以沒有初始值

set

@row_number=0

;set

@pre_game_id=0

;select

*from

(select

@row_number:=if(

@pre_game_id

= game_id,

@row_number+1

,1)as

'row_num'

, t.*,

@pre_game_id:=game_id as

'game_id2'

from

(select

h.id as

'hospital_id'

, h.name as

'hospital_name'

, p.id as

'patient_id'

, p.name as

'patient_name'

, p.gender,

ed.game_id, g.name as

'game_name'

, g.limb, ed.score as

'game_score'

, wr.workout_date as

'workout_time'

from

t_p p,

t_w_r wr,

t_e_d ed,

t_h h,

t_g g

where

p.name =

'kenny'

and workout_date >=

'2010-09-11'

and p.id = wr.patient_id

and wr.id = ed.workout_id

and p.hospital_id = h.id

and ed.game_id = g.id

-- mysql 不需要此 group by,加了會報錯 this is incompatible with sql_mode=only_full_group_by

group

by game_id, game_score, workout_time

order

by game_id, game_score desc

, workout_time desc

) t) m

where

row_num =

1-- mariadb 不需要此 order by,加了也沒關係

order

by game_id

注意:

如果以上試驗有錯誤或跟實際情況有出入,請試驗正確後採用

如果考慮資料庫效能,也可以根據業務需要拆分到程式中實現

不建議一開始就在程式中寫n多步驟的**才東拼西湊,還不如簡單粗暴乙個sql實現效能棒

mongodb 分組 得到第一條資料

業務邏輯 控制器每分鐘上報採集資料,現需得到每個控制器的每種採集資料的最近一條資料 效能比較低。分組,得到每個控制器每種採集型別的離當前最近的一條記錄 private static void group if curr.createdate result.createdate string fina...

LINQ分組取出第一條資料

person1 id 1,name test1 person2 id 1,name test1 person3 id 2,name test2 以上list如果直接使用distinct方法進行過濾,仍然返回3條資料,而需要的結果是2條資料。下面給出解這個問題的方法 方法1 distinct 方法中使...

SQL語句分組獲取記錄的第一條資料

使用northwind 資料庫 首先查詢employees表 查詢結果 city列裡面只有5個城市 使用row number over partition by col1 order by col2 先進行分組 注 根據col1分組,在分組內部根據 col2排序,而此函式計算的值就表示每組內部排序後...