2017-02-11 52 views
1

我有一個表,看起來像這樣的分組...的MySQL的細節

user_id, match_id, points_won 
1   14   10 
1   8   12 
1   12   80 
2   8   10 
3   14   20 
3   2   25 

我想寫一個MySQL腳本,拉回積分最高的用戶在一場比賽中贏得了和包括match_id在結果 - 換句話說...

user_id, match_id, max_points_won 
1   12   80 
2   8   10 
3   2   25 

當然,如果我沒有需要match_id我只是做...

select user_id, max(points_won) 
from table 
group by user_id 

但是,只要我將match_id添加到「select」和「group by」中,我對每個匹配都有一行,如果我只將match_id添加到「select」(而不是「group by」),不正確地與points_won相關。

理想我不想做下面可能是因爲它不感到特別安全(例如,如果用戶已經贏得了多個匹配點相同數量的)...

SELECT t.user_id, max(t.points_won) max_points_won 
, (select t2.match_id 
    from table t2 
    where t2.user_id = t.user_id 
    and t2.points_won = max_points_won) as 'match_of_points_maximum' 
FROM table t 
GROUP BY t.user_id 

是這個問題還有更多優雅的選擇嗎?

回答

2

這比它需要在MySQL中更難。一種方法是一種黑客攻擊,但它在大多數情況下都有效。這是group_concat()/substring_index()招:

select user_id, max(points_won), 
     substring_index(group_concat(match_id order by points_won desc), ',', 1) 
from table 
group by user_id; 

group_concat()符連接在一起的所有match_id S,通過降分排序。 substring_index()然後採取第一個。

兩個重要的注意事項:

  • 所得表達具有字符串類型,而不管內部型的。
  • group_concat()使用內部緩衝區,其默認長度爲1,024個字符。該默認長度可以更改。
+0

謝謝戈登 - 黑客或不,實際上正是我想要的! – d3wannabe

1

您可以使用查詢:

select user_id, max(points_won) 
from table 
group by user_id 

作爲派生表。加入這個原始表得到你想要的東西:

select t1.user_id, t1.match_id, t2.max_points_won 
from table as t1 
join (
    select user_id, max(points_won) as max_points_won 
    from table 
    group by user_id 
) as t2 on t1.user_id = t2.user_id and t1.points_won = t2.max_points_won 
+0

感謝Giorgos - 這是一個非常好的解決方案,但我(也許是不必要的)擔心從最大連接回points_won(例如,如果有一個在相同的最高點的多條記錄) – d3wannabe

0

編輯:只限於PostgreSQL,SQL服務器,甲骨文

您可以使用ROW_NUMBER:

SELECT USER_ID, MATCH_ID, POINTS_WON 
FROM 
(
    SELECT user_id, match_id, points_won, row_number() over (partition by user_id order by points_won desc) rn 
    from table 
) q 
where q.rn = 1 

對於類似的功能,請看Gordon Linoff的回答或在這article

在你的例子中,你對每個用戶的結果集進行劃分,然後你通過points_won desc命令來首先獲得最高得分點。

+0

對不起devoh - 但我得到一個「運行時檢查與你的MySQL服務器版本相對應的手冊」 - 當然也可能是其他版本的有效解決方案 – d3wannabe

+0

我的不好。我不知道mysql不支持像Sql-Server,Oracle或Postgre這樣的row_number()。 – devoh

0

我認爲你可以通過在內部查詢中添加限制1來優化你的查詢。

SELECT t.user_id, max(t.points_won) max_points_won 
, (select t2.match_id 
    from table t2 
    where t2.user_id = t.user_id 
    and t2.points_won = max_points_won limit 1) as 'match_of_points_maximum' 
FROM table t 
GROUP BY t.user_id 
+0

謝謝algojava - 唯一的問題是,我認爲我的原始示例查詢可能有缺陷 - 我得到一個「參考'max_points_won'不支持(參考組函數)」錯誤時運行此 – d3wannabe