2010-06-22 40 views
0

我有一個表,看起來是這樣的:如何做 '分級' 純(即ANSI)SQL

CREATE TABLE student_results(ID整數,名稱VARCHAR(32),得分浮動);

讓我們做出以下兩個假設:

  1. 假設比分從0到最大的100
  2. 假設我想年級學生在10
「步長」

所以我想申請以下等級:

Score  Grade Awarded 
0-10  GRADE9 
10-20  GRADE8 
20-30  GRADE7 
30-40  GRADE6 
40-50  GRADE5 
50-60  GRADE4 
60-70  GRADE3 
70-80  GRADE2 
80-90  GRADE1 
99-100  GENIUS 

我想編寫一個SQ L查詢需要輸入以下參數:

lowest score: 0 in this example 
highest score: 100 in this example 
'step' size: 10 in this example 

儘可能地,如果可能的話,我想用ANSI SQL編寫這樣的查詢。如果我必須選擇一個數據庫,然後按優先順序,它必須是:

  • PostgreSQL的
  • MySQL的

可能有人請解釋我是如何可能能寫的使用上表作爲示例進行這種評分的SQL查詢?

[編輯]

Sample input data 

1, 'homer', 10.5 
2. 'santas little helper', 15.2 
3, 'bart', 20.5 
4, 'marge', 40.5 
5. 'lisa', 100 

我將有一個SQL函數grade_rank() - 即排名學生:

的功能grade_rank()的參數是:

1st argument: LOWEST possible score value 
2nd argument: HIGHEST possible score value 
3rd argument: step size, which determines the levels/divisions between the ranks 

select id, name, grade_rank(0,100, 10) grade from student_scores; 

的輸出(基於上面的輸入)應該是:

1, homer,    GRADE9 
2. santas liitle helper GRADE9 
3, bart,    GRADE8 
4, marge,    GRADE6 
5. lisa,    GENIUS 
+1

你能從這樣的查詢發表您的預期輸出的例子? – Oded 2010-06-22 10:06:33

+0

你問的是如何使用'BETWEEN'而不是'='做一個連接? – 2010-06-22 10:12:41

+0

您的原始評分列表僅處理整數,但編輯部分中的示例數據指的是在原始邊界之間的實數。例如。 10.5在GRADE9和GRADE8之間。您應該編輯一個或另一個,以準確顯示您希望如何工作。我*認爲*到目前爲止提供的答案只適用於整數值。 – Mike 2010-06-22 11:17:56

回答

1

通過這種方式,你可以做到這一點比較一般,但成績會以相反的順序,從1開始直至N,即

  • 0-10 Grade1
  • 10-20 Grade2
  • 20-30 Grade3
  • 30-40 Grade4
  • ...

例如使用值 步驟10 得分43

該算法

SELECT (((score-1)-((score-1) % step))/step)+1

將返回5

您不必知道最高分。如果最高分數爲100,則沒有人能夠執行高於100的操作,您只需確定步驟的大小即可。例如,如果你想要步長爲25.知道最高分數爲100,則會有4個等級。所以一步級別設置爲25,而不是10的結果將是2,即2級。

SELECT (((43-1)-((43-1) % 25))/25)+1 

也許不是發現你所期望的,但也許通用的,足以有用的權利。這是函數在SQL中的樣子。

CREATE OR REPLACE FUNCTION grade_rank(IN score integer, IN step integer, OUT rank integer) 
AS 'SELECT ((($1-1)-(($1-1) % $2))/$2)+1' 
LANGUAGE 'SQL'; 

現在調用這個函數

select * from grade_rank(43,10) 

返回5

而且這個PLPGSQL相當於:

CREATE OR REPLACE FUNCTION grade_rank(IN score integer, IN step integer) 
    RETURNS integer AS 
$BODY$ 
DECLARE rank integer; 
BEGIN 
    SELECT (((score-1)-((score-1) % step))/step)+1 INTO rank; 
    RETURN rank; 
END; 
$BODY$ 
    LANGUAGE 'plpgsql'; 
1

這樣的事情?

SELECT 
    [name], 
    score, 
    CASE 
      WHEN score > @max - @stepsize THEN 'GENIUS' 
      ELSE CONCAT('GRADE', 
        CAST(
         FLOOR((@max - score)/@stepsize - 
           CASE score 
            WHEN @min THEN 1 
            ELSE 0 
           END CASE 
         ) as char(3) 
        ) 
       ) 
    END CASE 
FROM 
    student_results 

你可能要調整了一點 - 我不明白最小部分(因爲最後的範圍是1個大小比其他範圍更大的是它僅使用?)

編輯

更名@step到@stepsize爲清楚起見每伊瓦爾(@step可能被誤解爲步數)

+0

+1 - 我相信你的SQL是更標準的然後我的,也是不錯的情況 – Unreason 2010-06-22 10:53:58

+0

-1只適用於當前的評分等級。如果@min!= 0,@step!= 10或@max!= 100 ...會失敗@ – 2010-06-22 11:00:28

+0

@Ivar Bonsaksen - 你能否提供一個組合,並記錄哪一個失敗?我嘗試了0-110步驟11,它工作正常。謝謝! – potatopeelings 2010-06-22 11:18:20

1

有幾個選項:

1) 創建(最小,最大)並加入表格

SELECT score, grades.grade 
FROM table 
    INNER JOIN grades ON table.score >= grades.min AND table.score <= grades.max 

2) 創建臨時表(或甚至從DUAL選擇)和替代等級的上述連接就可以了,比如你可以編寫子查詢

(SELECT 0 as MIN, 10 as max, 'GRADE9' as grade FROM DUAL 
UNION ALL 
SELECT 11 as MIN, 20 as max, 'GRADE8' as grade FROM DUAL 
UNION ALL 
... 
SELECT 91 as min, 100 as max, 'GENIUS' as grade FROM DUAL 
) AS grades 

3) 使用的情況下

SELECT score, 
    CASE WHEN score = 0 THEN 'GRADE9' 
     WHEN score >= 1 AND score <= 90 THEN 'GRADE' || (9 - (score-1)/10) 
     WHEN score >= 91 THEN 'GENIUS' 
     ELSE 'ERROR' 
    END grade 
FROM table 

(請注意,在上面的查詢,你可以替代0,100和10的最低,最高和步驟,以獲得動態sql)

4) 創建user function(但是這將讓RDBMS專用)

1

這個怎麼樣? (原來我用@steps,在步數,而不是@step。如果你指定,而@step,@steps可以被計算爲@steps = (@[email protected])/@step

SET @lowest = 0; 
SET @highest = 100; 
SET @steps = 10; 

SELECT 
    name, 
    CASE 
     WHEN score >= (@[email protected]) THEN 'GENIUS' 
     ELSE 
      CONCAT(
       'GRADE', 
       @steps-FLOOR(([email protected])/((@[email protected])/@steps))-1) 
    END 
FROM 
    student_results 

這會給你一個只要你通過下一步新的檔次。

0-9.999 => GRADE1 
10-19.999 => GRADE2 
etc. 
+0

我想你在測試'GENIUS'時需要從@highest中減去@step。 – Mike 2010-06-22 10:53:19

+0

我想你可能想調整一下。 90分不給GRADE1(或者我計算錯誤,通常發生:-)) – potatopeelings 2010-06-22 11:31:42