2009-11-04 98 views
0

我有如下表(高分),MySQL的:獲得最高分數用戶

id  gameid  userid  name  score  date 
1  38   2345  A   100  2009-07-23 16:45:01 
2  39   2345  A   500  2009-07-20 16:45:01 
3  31   2345  A   100  2009-07-20 16:45:01 
4  38   2345  A   200  2009-10-20 16:45:01 
5  38   2345  A   50   2009-07-20 16:45:01 
6  32   2345  A   120  2009-07-20 16:45:01 
7  32   2345  A   100  2009-07-20 16:45:01 

現在,在上述結構中,用戶可以玩遊戲多次,但我想顯示「已賽「由特定用戶。所以在玩遊戲的部分,我無法展示多款遊戲。所以這個概念應該就像用戶玩過3次遊戲一樣,然後應該顯示最高分的遊戲。

我要像結果數據:

id  gameid  userid  name  score  date 
2  39   2345  A   500  2009-07-20 16:45:01 
3  31   2345  A   100  2009-07-20 16:45:01 
4  38   2345  A   200  2009-10-20 16:45:01 
6  32   2345  A   120  2009-07-20 16:45:01 

我嘗試下面的查詢,但它不是給我正確的結果:

SELECT id, 
     gameid, 
     userid, 
     date, 
     MAX(score) AS score 
    FROM highscores 
WHERE userid='2345' 
GROUP BY gameid 

請告訴我這將是這樣做的查詢?

感謝

+0

怎麼樣打破僵局的處理 - 當有2+記錄相同的遊戲和用戶使用相同的高分?最近的日期? – 2009-11-04 05:22:36

+0

@rexem:在這種情況下,它將返回2中的1條記錄。 – Prashant 2009-11-04 05:46:00

+0

@Prashant:是的,但是基於什麼標準? – 2009-11-04 06:10:38

回答

2

你有你的SELECT(當GROUP BY子句存在的話)的每個字段必須在該組的領域中的任何一個BY子句,否則一組函數如MAX,SUM,AVG等等。在你的代碼中,userid在技術上違反了這個規定,但是以非常無害的方式(你可以使你的代碼在技術上符合SQL標準GROUP BY gameid, userid);字段iddate的違規情況更嚴重 - 在一個GROUP BY集合中將會有許多ID和日期,並且您不會告訴如何從該集合中創建單個值(MySQL選擇一個或多或少的隨機數據,更嚴格的SQL引擎可能會更有幫助地給你一個錯誤)。

我知道你想要the ID和日期對應於給定分組的最高分數,但這在代碼中並不明確。你需要一個子選擇或自聯接才能使其變得明確!

7

要求是有點模糊/混亂,但會這樣的事情滿足需求?
(有意添加各種可能感興趣的聚集體)。

SELECT gameid, 
     MIN(date) AS FirstTime, 
     MAX(date) AS LastTime, 
     MAX(score) AS TOPscore. 
     COUNT(*) AS NbOfTimesPlayed 
FROM highscores 
WHERE userid='2345' 
GROUP BY gameid 
-- ORDER BY COUNT(*) DESC -- for ex. to have games played most at top 

編輯:有關將ID列的SELECT列表
簡短的回答是新的問題:「沒有,身份證不能添加,沒有這種特殊的構造內」。 (進一步閱讀以瞭解原因)然而,如果意圖使遊戲的ID得分最高,則可以使用子查詢來修改查詢以實現該目的。

正如Alex M在本頁中所解釋的那樣,必須包括SELECT列表中引用的所有列名,以及未在集合函數(MAX,MIN,AVG,COUNT等)的上下文中使用的列名在ORDER BY子句中。 SQL語言這條規則的原因很簡單,就是在收集結果列表的信息時,SQL可能會遇到這樣的列的多個值(列在SELECT中但不是GROUP BY),然後不知道如何處理它;而不是做任何事情 - 可能有用但可能很愚蠢 - 對於這些額外的行/值,SQL標準指定了錯誤消息,以便用戶可以修改查詢並明確表達他/她的目標。

在我們的具體情況中,我們可以在SELECT中添加id並將其添加到GROUP BY列表中,但這樣做時發生聚合的分組將不同:結果列表將包括很多行,因爲我們有id + gameid組合,每行的聚合值將僅基於來自表的記錄,其中id和gameid具有相應的值(假設id是表中的PK,我們會得到每個聚合一行,使得MAX()等毫無意義)。

用子查詢來包含對應於具有最高分的遊戲的id(以及可能的其他列)的方式。這個想法是子查詢選擇TOP分數的遊戲(在給定的分組內),並且主要查詢的SELECT選擇該行的任何列,即使子查詢的組中沒有(不可能) - 構造。順便說一句,在這個頁面上給予獎勵以便首先顯示這種類型的查詢。

SELECT H.id, 
     H.gameid, 
     H.userid, 
     H.name, 
     H.score, 
     H.date   
FROM highscores H 
JOIN (
    SELECT M.gameid, hs.userid, MAX(hs.score) MaxScoreByGameUser 
    FROM highscores H2 
    GROUP BY H2.gameid, H2.userid 
) AS M 
    ON M.gameid = H.gameid 
     AND M.userid = H.userid 
     AND M.MaxScoreByGameUser = H.score 
WHERE H.userid='2345' 

關於上述

  • 重複查詢的一些重要講話:如果用戶玩幾個遊戲,達到了同喜分數,查詢會產生很多行。
  • GROUP BY的子查詢可能需要更改爲查詢的不同用途。如果不是在每個用戶的基礎上搜索遊戲的高分,我們希望獲得絕對的高分,我們需要從GROUP BY中排除userid(這就是爲什麼我使用明確的長名稱命名MAX的別名)
  • 爲了提高效率,可以在子查詢的[現在不存在] WHERE子句中添加userid ='2345'(除非MySQL的優化器非常聰明,目前所有遊戲+用戶組合的所有高分計算,因此我們只需要這些用戶'2345');向下複製;解;變量。

有幾種方法可以解決上面提到的問題,但是這些似乎超出了對GROUP BY結構[現在相當簡單]的解釋的範圍。

+0

我們可以在此查詢中包含「id」字段嗎?當我包含它時,它不會給出正確的'id'? – Prashant 2009-11-04 07:25:35

+0

@Prashant:由於你是由gameid分組的,它不會是正確的'id'。因此'id'可能包含在分組 – 2009-11-04 07:35:28

+0

@Kevin Peno期間發現的最後一條序號記錄,感謝您的快速響應。 @Prashant,我編輯了一個更長的解釋,說明爲什麼使用子查詢不能添加[在這個構造中]以及它是如何可能的。 – mjv 2009-11-04 15:55:22

1

用途:

SELECT t.id, 
     t.gameid, 
     t.userid, 
     t.name, 
     t.score, 
     t.date   
    FROM HIGHSCORES t 
    JOIN (SELECT hs.gameid, 
       hs.userid, 
       MAX(hs.score) 'max_score' 
      FROM HIGHSCORES hs 
     GROUP BY hs.gameid, hs.userid) mhs ON mhs.gameid = t.gameid 
             AND mhs.userid = t.userid 
             AND mhs.max_score = t.score 
WHERE t.userid = '2345'