mysql中沒有相似oracle和postgreSQL的 OVER(PARTITION BY)功能. 那麼如何在MYSQL中搞定分組聚合的查詢呢html
先說結論: 利用 group_concat + substr等函數處理mysql
例如: 訂單表一張, 只保留關鍵字段sql
id | user_id | money | create_time |
1 | 1 | 50 | 1420520000 |
2 | 1 | 100 | 1420520010 |
3 | 2 | 100 | 1420520020 |
4 | 2 | 200 | 1420520030 |
業務: 查找每一個用戶的最近一筆消費金額oracle
單純使用group by user_id, 只能按user_id 將money進行聚合, 是沒法將最近一單的金額篩選出來的, 只能知足這些需求, 例如: 每一個用戶的總消費金額 sum(money), 最大消費金額 max(money), 消費次數count(1) 等函數
可是咱們有一個group_concat能夠用, 思路以下:post
1. 查找出符合條件的記錄, 按user_id asc, create_time desc 排序; spa
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);code
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 函數進行切分便可htm
完整SQL, 注意group_concat的內排序, 不然順序不保證, 拿到的就不必定是第一個了blog
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
有任何問題請不吝賜教, 謝謝!