MySQL查詢最大值(最小值)或前n個最大(最小)值的方法分析
在實際中,我們可能會有這樣的需求,就是從資料庫中查出某個欄位的最大值或最小值,或者查出前n個最大(最小)值。例如,查出某個學生成績中最好的一個或者查出排名在前5名的學生成績等。下面簡要給出一些示例查詢程式碼。
我們的表結構如下圖:
stuname
欄位相當於學生的姓名,score
代表分數,id
為主鍵 ;
表資料準備如下:
一、查詢最大(最小值)
在這裡我們要分別查詢出某個學生中的分數的最大值,這裡可有兩種查詢方法。
1
SELECT a.stuname,MAX(a.score) AS score FROM stuscore a GROUP BY a.`stuname` ;
在這個語句中,我們通過對stuname
欄位進行分組,然後再用MAX()
函式對每組中的最大值進行計算。
2、使用連線
SELECT a.stuname,a.score AS score FROM stuscore a JOIN
stuscore b ON a.`stuname`=b.`stuname`
GROUP BY a.`score` HAVING a.`score`=MAX(b.`score`);
在第二條sql語句中,我們以stuname
為判斷條件,對兩個表進行連線操作。如果只執行SELECT a.stuname,a.score AS score FROM stuscore a JOIN
stuscore b ON a.
=b.
stuname我們會得到下面的結果集: 之所以會得到這個結果集,是因為在連線時,左表中的每條記錄都會根據連線條件
ON a.
stuname=b.
stuname“和右表中的每條記錄進行匹配,這就是為什麼會出現重複記錄的原因。這個有點像程式語言中的“雙重迴圈”。
然後再加分組和分組條件GROUP BY a.
score HAVING a.
score=MAX(b.
score)
,就可以得到每個學生中的最大分數;
其實GROUP BY a.`score ` HAVING a.`score`=MAX(b.`score`)
這個分組條件一開始我也是有點不大理解,就是說我是根據score
MAX()
函式為什麼就可以計算出每個學生中的最大分數,我們知道第一種方法比較好理解就是對每個學生的姓名分組,然後用MAX()
函式計算出其中的最大值,這是肯定的,但第二方法是對score
欄位進行分組的。在這裡我覺得原因應該是,在將兩個表進行連線時,連線條件a.
stuname=b.
stuname` 已經對這些記錄根據學生姓名進行分組了,所以
MAX(b.score
)`才可以計算出每個學生中的最大分數。 二、前n個最大(最小)值
在這裡,我要查詢出,每個學生中,排名前兩位的分數。大概思路是,對以姓名為分組的每條記錄,首先要查詢某個記錄在它所屬的組別中,所有大於該記錄的分數的記錄數,然後根據到的記錄數,就可以對這個結果集進行過慮了。首先來看程式碼和效果。
SELECT c.stuname,c.score FROM (SELECT a.stuname,a.score,(SELECT COUNT(*) FROM stuscore b WHERE b.score>a.score AND b.stuname=a.stuname) AS cnt
FROM stuscore a ) c WHERE c.cnt<=1 GROUP BY c.stuname,c.score;
這個確實得到了我們想要的結果集。
來分析 一下
在這個查詢中的SELECT a.stuname,a.score,(SELECT COUNT(*) FROM stuscore b WHERE b.score>a.score AND b.stuname=a.stuname) AS cnt
子查詢執行得到的結果集如下:
FROM stuscore a;
cnt
就是得到某個記錄在它所屬的組別中,所有大於該記錄的分數的記錄數。以姓名為zzz,分數為70的記錄為例,它的cnt值為1就代表在它所屬組別中,有1條記錄的分數比它高。其中cnt
欄位的計算我們又可以通過一個子查詢來完成SELECT COUNT(*) FROM stuscore b WHERE b.score>a.score AND b.stuname=a.stuname
,有了這個子查詢,當我們對每條記錄進行計算時,都要計算這個子查詢,這個子查詢的條件WHERE b.score>a.score AND b.stuname=a.stuname
就是限定在某個組別中查詢比該條記錄分數大的記錄,同時通過COUNT()
函式來計算符合條件的記錄數。
最後再根據得到的結果集進行過濾,以WHERE c.cnt<=1
為過濾條件(這裡取出最大和次大的分數值),就可以得到正確的結果集了。