2013-10-29 28 views
5

給定一個名爲表「等級」:如何將查詢返回行值的樣本作爲列?

STUDENT GRADE 
john  94 
john  76 
john  83 
john  87 
john  90 

我想查詢返回檔次的幾個例子爲每個學生,例如:

STUDENT GRADE1 GRADE2 GRADE3 GRADE4 
John  94  76  83  87 

注意只有4個樣品級列返回,但這個學生有超過4個等級。

我只知道如何返回使用MIN()和MAX()函數2個例年級在GROUP BY子句:

select student, min(grade), max(grade) 
from grades 
group by student 

是否有比最小值/最大值,使其他任何技巧或功能使用GROUP BY子句顯示超過兩個等級?

我寧願不寫我自己的存儲函數來做到這一點,除非它是查詢的一部分,而不是存儲在數據庫中。

我想到更多的功能,從MIN和MAX(如第二高,第三高等),除了記錄集返回其他值。

想法?

+0

這也可以使用聚合函數CASE表達式實現的呢? –

+0

@juergend如果我正確理解這個問題,我相信他想要選擇預設數量的隨機行(本例中爲4)進行採樣。 – pseudocoder

+0

學生將有最大數量的分數嗎? – logixologist

回答

0

我建議這樣的事情。唯一的限制是你不能顯示例子1到n,你僅限於確定的數字。

SELECT DISTINCT student, 
(
    select top 1 grade from 
    (select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 1 
) AS GRADE1 , 
(
    select top 1 grade from 
    (select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 2 
) AS GRADE2, 
(
    select top 1 grade from 
    (select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 3 
) AS GRADE3, 
(
    select top 1 grade from 
    (select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 4 
) AS GRADE4 
from grades g 

使用遊標。在這個解決方案,您將有1到N個結果

DECLARE @grade int 
DECLARE @n int 

DECLARE @sql varchar(max) 

DECLARE _cursor CURSOR FOR 
    SELECT grade 
    FROM grade 
    WHERE student like 'XXX' 

OPEN _cursor 
FETCH NEXT FROM _cursor INTO @grade 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF @sql like '' 
    begin 
     set @sql = 'SELECT ' + 'XXX' + ' AS Student ' 
    end 
    set @sql = @sql + ',' + @grade ' as GRADE'+ @n 
    set @n = @n + 1 
END 

CLOSE _cursor 
DEALLOCATE _cursor 

exec(@sql) 

這一產量將

STUDENT GRADE1 GRADE2 GRADE3 GRADE4 
John  94  87  83  76 
+0

其他可能的解決方案是使用** **遊標 – Federico

+0

非常好。您是否知道這種技術能夠輕鬆應用於Oracle? – draca

+0

不,我不知道 – Federico

6

您可以通過應用row_number()功能,然後應用PIVOT得到的結果:

select student, 
    grade1 = [1], 
    grade2 = [2], 
    grade3 = [3], 
    grade4 = [4] 
from 
(
    select student, grade, 
    row_number() over(partition by student 
         order by grade desc) seq 
    from grades 
) d 
pivot 
(
    max(grade) 
    for seq in ([1], [2], [3], [4]) -- the # of grades you want returned 
) piv; 

SQL Fiddle with Demo

在PIVOT中使用的新列名將是您想要返回的等級數。分區中使用的ORDER BYgrade desc,但您也可以使用order by newid() to get a random result being returned來查看。你有一列表示這是第一個,第二個......年級

select student, 
    max(case when seq = 1 then grade end) grade1, 
    max(case when seq = 2 then grade end) grade2, 
    max(case when seq = 3 then grade end) grade3, 
    max(case when seq = 4 then grade end) grade4 
from 
(
    select student, grade, 
    row_number() over(partition by student 
         order by newid()) seq 
    from grades 
) d 
group by student; 

SQL Fiddle with Demo

相關問題