2013-10-29 7 views
5

Bei einer Tabelle mit dem Namen „Typen“:Wie Abfrage Abfragen von Zeilenwerten als Spalten zurückgeben?

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

Ich mag eine Abfrage für jeden Schüler ein paar Beispiele von Typen zurückzukehren, zum Beispiel:

STUDENT GRADE1 GRADE2 GRADE3 GRADE4 
John  94  76  83  87 

Hinweis gibt es nur 4 Probe Grad Spalten zurückgegeben, aber es gibt mehr als 4 Noten für diesen Schüler.

ich nur wissen, wie 2 Beispiel Noten zurückzukehren, um die min() und max() Funktionen in einer GROUP BY-Klausel:

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

es irgendwelche Tricks oder andere Funktionen als min/max, die ermöglichen wird, Anzeige von mehr als nur 2 Noten mit der GROUP BY-Klausel?

Ich würde lieber nicht meine eigene gespeicherte Funktion schreiben, um dies zu tun, es sei denn, es wäre Teil der Abfrage und nicht in der Datenbank gespeichert.

Ich denke an weitere Funktionen, die andere Werte aus dem Recordset neben der MIN und MAX zurückgegeben (wie die zweithöchste, dritthöchste usw.).

Ideen?

+0

Sie eine Spalte haben Sie die angibt, welche die ersten, zweiten ... grade? –

+0

@juergend Wenn ich die Frage richtig verstehe, glaube ich, dass er eine voreingestellte Anzahl von zufälligen Reihen (4 in diesem Beispiel) auswählen möchte, um zu probieren. – pseudocoder

+0

Gibt es eine maximale Anzahl an Noten, die ein Schüler haben wird? – logixologist

Antwort

0

Ich schlage so etwas vor. Die einzige Beschränkung ist, dass Sie die Beispiele 1 bis n nicht anzeigen können, Sie sind auf die festgelegte Anzahl beschränkt.

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 

Mit Cursors. Bei dieser Lösung werden Sie 1 bis n hatte

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) 

Ergebnisse wird diese Ausgabe

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

Andere mögliche Lösung verwendet ** Cursors ** – Federico

+0

Sehr gut. Wissen Sie, wie einfach diese Technik auf Oracle angewendet werden kann? – draca

+0

Nein, weiß ich nicht – Federico

6

Sie das Ergebnis durch die Anwendung der row_number() Funktion erhalten werden kann und die Anwendung dann die 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; 

Siehe SQL Fiddle with Demo.

Die neuen Spaltennamen, die in PIVOT verwendet werden, sind die Anzahl der Noten, die zurückgegeben werden sollen. Die in der Partition verwendete ORDER BY ist grade desc, aber Sie können auch mit suchen.

Dies auch erreicht werden könnte, eine Aggregatfunktion mit einem CASE-Ausdruck mit:

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 Siehe

Verwandte Themen