2013-11-22 53 views
1

我有一個3列的表,student_id,section_idmarks,每個都包含整數值,其中student_id是具有唯一值的主字段。現在我需要編寫以下3個場景查詢(PS:這僅僅是爲了學習的目的,所以這將是巨大的,如果你能告訴我,如果可能的一些替代的邏輯方法):Mysql查找來自每個組的多行

  1. 找到學生誰在每個部分排名第三。
  2. 查找每個部分中排名第2,3,4的學生。
  3. 找到每個部分中排名第4的學生,如果有任何限制條件,如果某個部分中有多個學生的標記相同,則跳過下一個等級。因此,假設有3名學生獲得了相同的分數,這些分數將在一個分區中排名第二,然後跳過第三和第四分數,並且下一名得分低於他們的學生將排在第五名。

對於第一個我想:

SELECT * FROM `students` s 
WHERE s.student_id= 
(
    SELECT student_id 
    FROM students 
    WHERE s.section_id=section_id 
    ORDER BY marks DESC 
    LIMIT 2,1 
) 
GROUP BY section_id 
ORDER BY marks DESC 

這工作,雖然我不知道關於優化。

在接下來的一個我用IN原因,否則我不能在子查詢取多行嘗試,但它說,MySQL不支持LIMITIN條款,有沒有什麼辦法來修改這個查詢第二種情況?

最後,我不知道該怎麼做第三個。

我在http://sqlfiddle.com/#!2/6442fb/1

讚賞任何幫助創建了一個測試表。

+0

選中此http://stackoverflow.com/questions/2160262/query-for-second-maximum-salary -from-employee-table – Damodaran

+0

這是有效的,但它是一個'無證'的解決方案(除非你在處理這個東西的手冊頁面上計算用戶評論部分)。 – Strawberry

回答

0

不幸的是,MySQL仍然缺乏對分析功能的支持。特別是RANK()RANK_DENSE()會很有幫助。效仿他們的一種方式是通過使用用戶變量:

SELECT student_id, section_id, marks 
    FROM 
(
    SELECT s.*, @n := IF(@s = section_id, IF(@m = marks, @n, @n + 1), 1) rank, 
     @s := section_id, @m := marks 
    FROM students s CROSS JOIN (SELECT @n := 0, @s := NULL, @m := NULL) i 
    ORDER BY section_id, marks DESC 
) q 
WHERE rank = 3 
ORDER BY marks DESC; 

SELECT student_id, section_id, marks 
    FROM 
(
    SELECT s.*, @n := IF(@s = section_id, IF(@m = marks, @n, @n + 1), 1) rank, 
     @s := section_id, @m := marks 
    FROM students s CROSS JOIN (SELECT @n := 0, @s := NULL, @m := NULL) i 
    ORDER BY section_id, marks DESC 
) q 
WHERE rank BETWEEN 2 AND 4 
ORDER BY section_id, marks DESC; 

SELECT student_id, section_id, marks 
    FROM 
(
    SELECT s.*, @n := IF(@s = section_id, @n + 1, 1), 
     @rn := IF(@m = marks, @rn, @n) rank, 
     @s := section_id, @m := marks 
    FROM students s CROSS JOIN (SELECT @n := 0, @rn := 0, @s := NULL, @m := NULL) i 
    ORDER BY section_id, marks DESC 
) q 
WHERE rank = 4 
ORDER BY marks DESC; 

這裏是SQLFiddle演示

+0

哇,看起來很棒,效果很棒!但是,你能解釋一下這個問題嗎?我試着查找用戶變量,但後來在上面的交叉連接處丟失了。 – Bluemagica

+0

@Bluemagica'CROSS JOIN'只用於初始化變量。在內部select中,我們正確地命令結果集,並且在選擇行時,我們通過比較'section_id'和'marks'的當前值與前一行('@ s'和'@ m')的值來計算等級;如果我們遇到一個新的部分ID,我們將計數器重置爲1,否則我們檢查標記的當前值是否等於前一行的值,而不是我們保持等級相同,否則我們給它加'1'。在外部選擇中,我們只篩選除目標等級以外的所有內容。前兩個查詢模擬'RANK_DENSE()'和第三個'RAN – peterm