2012-02-21 8 views
88

W MySQL jak zdefiniować niestandardową kolejność sortowania.Jak zdefiniować zamówienie ORDER BY w mySQL

Aby spróbować wyjaśnić, co chcę rozważyć tę tabelę:

ID Language Text 
0 ENU   a 
0 JPN   b 
0 DAN   c  
1 ENU   d 
1 JPN   e 
1 DAN   f 
2 etc... 

tutaj chcę zwrócić wszystkie wiersze posortowane według języka i rosnącym ID tak, że język = POL przychodzi, potem JPN i wreszcie Dan.

wynik powinien być następujący: A, D, B, E, C, F i tak dalej

jest to w ogóle możliwe?

Odpowiedz

195

MySQL ma przydatną funkcję o nazwie FIELD(), która doskonale nadaje się do takich zadań.

ORDER BY FIELD(Language,'ENU','JPN','DAN'), ID

Uwaga jednak, że

  1. To sprawia, że ​​SQL mniej przenośne, jak inne DBMS może nie mieć takiej funkcji

  2. Gdy lista języków (lub innych wartości do sortuj według) jest znacznie dłuższy, lepiej jest mieć osobną tabelę z kolumną sortorder i dołączyć do zapytań do zamawiania.

+2

Dzięki temu doskonale pasuję do mojej sytuacji, w której muszę zamówić dwie wartości (język podstawowy, na przykład JPN i język zastępczy, na przykład ENU). – Muleskinner

+1

Man właśnie uratowałeś mi przepisanie w magento :) –

+1

Co, jeśli masz "GROUP BY" przed? Na przykład pierwsza żądana wartość pojawia się na końcu? – Pathros

31

Jeśli są to tylko trzy wartości, a następnie można użyć a CASE expression:

ORDER BY `ID`, 
     CASE `Language` 
     WHEN 'ENU' THEN 1 
     WHEN 'JPN' THEN 2 
     WHEN 'DAN' THEN 3 
     END 

(Gdybym mógł tam być inne wartości, to może warto dodać kilka dodatkowych logiki zachować kolejność zgodna, na przykład , można dodać do tego CASEELSE 4 ekspresji, a następnie uporządkuj Language się jako trzecie kryterium kolejność:

ORDER BY `ID`, 
     CASE `Language` 
     WHEN 'ENU' THEN 1 
     WHEN 'JPN' THEN 2 
     WHEN 'DAN' THEN 3 
     ELSE 4 
     END, 
     `Language` 
) 
+1

A jeśli istnieje wiele wartości językowe można mieć osobną tabelę przechowującą każdego języka plus kolumny porządek i link do tej – kaj

+0

To zamówienie przez ID pierwsze, w wyniku, b, c, d, e , f – piotrm

+0

Dzięki temu działa idealnie - podobnie jak odpowiedź Mchl, którą zaakceptowałem, ponieważ wygląda na prostsze. – Muleskinner

13

masz kilka opcji bezceremonialny, pierwszy jest zmiana języka być ENUM (zakładając, że jest to możliwe, a ty spodziewasz się tylko kilku odmian)

Jeśli określisz je jako ENUM('ENU','JPN','DAN'), wtedy ORDER Language ASC zamawia w określonej przez ciebie kolejności.

Drugi będzie obejmować przypadek gdzieś, tj

SELECT * FROM table 
ORDER BY CASE Language 
    WHEN 'ENU' THEN 3 
    WHEN 'JPN' THEN 2 
    WHEN 'DAN' THEN 1 
    ELSE 0 
END DESC, ID ASC 

Performance-mądry sposób ENUM powróci szybsze rezultaty, ale będzie więcej kłopotów, jeśli chcesz dodać więcej języków. Trzecią opcją byłoby dodanie tabeli normalizacji dla języków, ale w tym przypadku może to być przesada.

+0

Gdzie dokładnie wpisujesz 'ENUM ('ENU', 'JPN', 'DAN')'? – Pathros

+1

@pathros w definicji tabeli, określasz ją jako ENUM zamiast VARCHAR itd.Wewnętrznie MySQL przechowuje opcje ENUM w określonej kolejności i indeksuje je, a więc przy zamówieniu przez kolumnę ENUM w szczególności użyje tego wewnętrznego indeksu zamiast wartości ciągu (chyba że CAST() zostanie wykorzystany do powrotu do VARCHAR) –

+0

Czy nie powinno brzmieć "END DESC", "END CASE DESC"? –