2013-05-21 7 views
8

Wir GREATEST verwenden können größten Wert aus mehreren Spalten wie untenmysql - Get zwei größten Werte aus mehreren Spalten

SELECT GREATEST(mark1,mark2,mark3,mark4,mark5) AS best_mark FROM marks 

zu bekommen, aber jetzt will ich zwei Top-Marken aus allen (5) Noten zu bekommen.

Kann ich dies auf MySQL-Abfrage tun?

Tabellenstruktur (Ich weiß, es ist falsch - von jemandem erstellt):

student_id | Name | mark1 | mark2 | mark3 | mark4 | mark5 
+0

Was Ihre Tabellenstruktur ist – Jake1164

+0

@ Jake1164 Abfrage so ziemlich alles erklärt. – BlitZ

+0

http://stackoverflow.com/questions/5360894/get-the-second-highest-value-in-a-mysql-table –

Antwort

2

Dies ist nicht die eleganteste Lösung, aber wenn Sie nicht die Tabellenstruktur Sie Entpivotisierung die Daten können dann ändern können, und dann einen Benutzer definierten Variablen gelten für jede STUDENT_ID eine Zeilennummer zu erhalten. Der Code wird ähnlich der folgenden sein:

select student_id, name, col, data 
from 
(
    SELECT student_id, name, col, 
    data, 
    @rn:=case when student_id = @prev then @rn else 0 end +1 rn, 
    @prev:=student_id 
    FROM 
    (
    SELECT student_id, name, col, 
     @rn, 
     @prev, 
     CASE s.col 
     WHEN 'mark1' THEN mark1 
     WHEN 'mark2' THEN mark2 
     WHEN 'mark3' THEN mark3 
     WHEN 'mark4' THEN mark4 
     WHEN 'mark5' THEN mark5 
     END AS DATA 
    FROM marks 
    CROSS JOIN 
    (
     SELECT 'mark1' AS col UNION ALL 
     SELECT 'mark2' UNION ALL 
     SELECT 'mark3' UNION ALL 
     SELECT 'mark4' UNION ALL 
     SELECT 'mark5' 
    ) s 
    cross join (select @rn := 0, @prev:=0) c 
) s 
    order by student_id, data desc 
) d 
where rn <= 2 
order by student_id, data desc; 

SQL Fiddle with Demo See. Dies ergibt die oberen 2 Markierungen pro student_id. Die innere Unterabfrage führt eine ähnliche Funktion aus wie die Verwendung eines UNION ALL zum Entsperren, aber Sie werden nicht mehrmals mit der Tabelle abgefragt, um das Ergebnis zu erhalten.

+0

+1 für SQLFiddle. Das ist fantastisch. – Jonathan

+0

Ich denke OP wollte eine Spalte aus allen 5 Mark Spalten erstellen und dann die 2 höchsten Spalten auswählen. Nicht sicher, obwohl. Meine Lösung spiegelt das trotzdem wider. – silkfire

2

Ich denke, dass Sie Ihre Datenbank-Struktur ändern sollte, da mit, dass horizontal viele Markierungen (dh als Felder/Spalten) Sie bereits bedeutet, mache etwas falsch.

Setzen Sie stattdessen alle Ihre Markierungen in eine separate Tabelle, in der Sie eine Viele-zu-Viele-Beziehung erstellen und führen Sie dann die erforderlichen SELECT zusammen mit LIMIT. Vorschläge

:

  1. Erstellen Sie eine Tabelle, die Sie mark_types nennen. Spalten: id, mark_type. I sehen, dass Sie derzeit 5 Arten von Marken haben; es wäre sehr einfach zusätzliche Typen hinzuzufügen.
  2. ändern marks Tabelle 3 Spalten zu halten: id, mark/grade/value, mark_type (diese Spalte ausländische Einschränkungen mark_types).
  3. Schreiben Sie Ihre SELECT Abfrage mit Hilfe von Joins und GROUP BY mark_type.
+0

Tabellenstruktur, die von jemandem erstellt wurde, damit ich mich nicht einmischen möchte, ich brauche nur eine Lösung für die aktuelle Tabellenstruktur. – LoganPHP

0

Okay, hier ist eine neue Antwort, die ist mit der aktuellen Tabellenstruktur funktionieren soll:

SELECT `student_id`, `Name`, `mark` FROM (SELECT `student_id`, `Name`, `mark1` AS `mark` FROM `marks` 
              UNION ALL 
              SELECT `student_id`, `Name`, `mark2` AS `mark` FROM `marks` 
              UNION ALL 
              SELECT `student_id`, `Name`, `mark3` AS `mark` FROM `marks` 
              UNION ALL 
              SELECT `student_id`, `Name`, `mark4` AS `mark` FROM `marks` 
              UNION ALL 
              SELECT `student_id`, `Name`, `mark5` AS `mark` FROM `marks`) AS `marks` 
ORDER BY `mark` DESC 
LIMIT 2 
+0

sollten Sie auch 'student_id' und' name' angeben, sonst wird keine korrekte Ausgabe angezeigt. – Ravi

Verwandte Themen