2013-05-21 12 views
8

Możemy użyć GREATEST aby uzyskać największą wartość z wielu kolumn jak poniżejmysql - Get dwie największe wartości z wielu kolumn

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

Ale teraz chcę dostać dwa najlepsze oceny ze wszystkich (5) znaków.

Czy mogę to zrobić w zapytaniu mysql?

struktura tabeli (wiem, że jest źle - stworzony przez kogoś):

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

Jaki jest Twój struktury tabeli – Jake1164

+0

@ Jake1164 zapytania wyjaśnia prawie wszystko. – BlitZ

+0

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

Odpowiedz

2

To nie jest najbardziej eleganckie rozwiązanie, ale jeśli nie może zmienić strukturę tabeli następnie można UNPIVOT dane, a następnie zastosować zmiennej zdefiniowanej przez użytkownika, aby uzyskać numer wiersza dla każdego student_id. Kod będzie podobny do następującego:

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; 

Zobacz SQL Fiddle with Demo. Spowoduje to zwrócenie 2 najlepszych znaków za student_id. Podzapytanie wewnętrzne wykonuje podobną funkcję, jak użycie UNIONA WSZYSTKIEGO do rozpakowania, ale nie dostajesz zapytania o tabelę wiele razy, aby uzyskać wynik.

+0

+1 dla SQLFiddle. To jest niesamowite. – Jonathan

+0

Myślę, że OP chciał utworzyć kolumnę spośród WSZYSTKICH kolumn z 5 znakami, a następnie wybrać 2 najwyższe. Nie jestem tego pewien. Moje rozwiązanie i tak to odzwierciedla. – silkfire

2

myślę, że należy zmienić strukturę bazy danych, ponieważ mający że wiele znaków w poziomie (czyli jak Pola/kolumny) oznacza już cię "Robię coś źle.

Zamiast tego umieść wszystkie swoje znaki w osobnej tabeli, w której tworzysz wiele do wielu relacji, a następnie wykonaj niezbędną SELECT wraz z LIMIT.

Sugestie:

  1. utworzyć tabelę, aby zadzwonić mark_types. Kolumny: id, mark_type. I Sprawdź, czy masz 5 typów znaków; byłoby bardzo proste , aby dodać dodatkowe typy.
  2. Zmień tabelę marks trzymać 3 kolumny: id, mark/grade/value, mark_type (kolumna ta zagranicznych ograniczenia do mark_types).
  3. Napisz zapytanie za pomocą SELECT za pomocą joins i GROUP BY mark_type.
+0

Struktura tabeli utworzona przez kogoś, więc nie chcę w tym przeszkadzać, tylko potrzebuję rozwiązania dla obecnej struktury tabeli. – LoganPHP

0

Ok oto nowa odpowiedź, że to powinno działać z obecną strukturą tabeli:

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

powinieneś również dołączyć 'student_id' i' name' inaczej ... nie wyświetli poprawnego wyniku. – Ravi

Powiązane problemy