Mysql 分組聚合實現 over partition by 功能


mysql中沒有類似oracle和postgreSQL的 OVER(PARTITION BY)功能. 那么如何在MYSQL中搞定分組聚合的查詢呢

 

先說結論: 利用 group_concat + substr等函數處理

 

例如: 訂單表一張, 只保留關鍵字段

id user_id money create_time
1 1 50 1420520000
2 1 100 1420520010
3 2 100 1420520020
4 2 200 1420520030

業務: 查找每個用戶的最近一筆消費金額

單純使用group by user_id, 只能按user_id 將money進行聚合, 是無法將最近一單的金額篩選出來的, 只能滿足這些需求, 例如: 每個用戶的總消費金額 sum(money), 最大消費金額 max(money), 消費次數count(1) 等

 

但是我們有一個group_concat可以用, 思路如下:

1. 查找出符合條件的記錄, 按user_id asc, create_time desc 排序; 

select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by ord.user_id asc , ord.create_time desc
user_id money create_time
1 100 1420520010
1 50 1420520000
2 200 1420520030
2 100 1420520020

 

2. 將(1)中記錄按user_id分組, group_concat(money);

select t.user_id, group_concat( t.money order by t.create_time desc ) moneys from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and ord.create_time > 0 order by ord.user_id asc , ord.create_time desc) t group by t.user_id

 

user_id moneys
1 100,50
2 200,100

3. 這時, 如果用戶有多個消費記錄, 就會按照時間順序排列好, 再利用 subString_index 函數進行切分即可

 

完整SQL, 注意group_concat的內排序, 否則順序不保證, 拿到的就不一定是第一個了

select t.user_id, substring_index(group_concat( t.money order by t.create_time desc ),',',1) lastest_money from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc) t group by user_id ; 

 

user_id moneys
1 100
2 200

利用這個方案, 以下類似業務需求都可以這么做, 如:

1. 查找每個用戶過去10個的登陸IP

2. 查找每個班級中總分最高的兩個人

 

補充: 如果是只找出一行記錄, 則可以直接只用聚合函數來進行

select t.user_id, t.money  from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc) t group by user_id ;

前提一定是(1) 只需要一行數據, (2) 子查詢中已排好序, (3) mysql關閉 strict-mode

 

參考資料:

http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sql-mode-strict

http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

 

有任何問題請不吝賜教, 謝謝!


免責聲明!

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



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