MySQL - wartości ORDER BY w IN ()

107

Mam nadzieję, że posortuję elementy zwrócone w poniższym zapytaniu według kolejności, w jakiej zostały wprowadzone do funkcji IN () .

WEJŚCIE:

SELECT id, name FROM mytable WHERE name IN ('B', 'A', 'D', 'E', 'C');

WYNIK:

|   id   |   name  |
^--------^---------^
|   5    |   B     |
|   6    |   B     |
|   1    |   D     |
|   15   |   E     |
|   17   |   E     |
|   9    |   C     |
|   18   |   C     |

Jakieś pomysły?

Matt
źródło

Odpowiedzi:

231
SELECT id, name
FROM mytable
WHERE name IN ('B', 'A', 'D', 'E', 'C')
ORDER BY FIELD(name, 'B', 'A', 'D', 'E', 'C')

Funkcja FIELD zwraca pozycję pierwszego ciągu na pozostałej liście ciągów.

Jednak znacznie lepszą wydajnością jest posiadanie zindeksowanej kolumny, która reprezentuje porządek sortowania, a następnie sortowanie według tej kolumny.

Ayman Hourieh
źródło
9
@Vladimir - tak, to jest specyficzne dla MySQL. Pytanie ma tag mysql.
Ayman Hourieh
Świetnie, zamiennik funkcji „dekodowania” Oracle po przełączeniu DB.
Martin Lyne
7
Ostrożny. Każda nieznana wartość właściwości (której nie ma na liście) będzie miała pierwszeństwo przed znanymi wartościami, tj FIELD(letter, 'A', 'C'). Lista najpierw zwróci wpisy z literą B jako pierwszą (przy założeniu zestawu rekordów z A | B | Cwartościami). Aby tego uniknąć, odwróć listę i użyj DESC, tj FIELD(letter, 'C', 'A') DESC.
Gajus
Jak to osiągnąć w SQL Server.
user123456
29

Inna opcja stąd: http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html

select * 
from tablename 
order by priority='High' DESC, priority='Medium' DESC, priority='Low" DESC;

Więc w twoim przypadku (niesprawdzone) byłoby

SELECT id, name
FROM mytable
WHERE name IN ('B', 'A', 'D', 'E', 'C')
ORDER BY name = 'B', name = 'A', name = 'D', name =  'E', name = 'C';

W zależności od tego, co robisz, uznałem to za trochę dziwaczne, ale zawsze działało po odrobinie zabawy.

joedevon
źródło
Może to być lepsze niż użycie funkcji field () jako kolejnej sugerowanej odpowiedzi, ponieważ użycie field () uniemożliwi użycie indeksu, ale ma szansę użyć indeksu za pomocą tej metody (chociaż nie jestem pewien, jak dobrze mógłby użyć indeksu)
ʞɔıu
4

Spróbuj czegoś takiego

... ORDER BY (CASE NAME WHEN 'B' THEN 0 WHEN 'A' THEN 1 WHEN ...
Vladimir Dyuzhev
źródło
3

Może to może komuś pomóc (p_CustomerId jest przekazywany w SP):

SELECT CompanyAccountId, CompanyName
FROM account
LEFT JOIN customer where CompanyAccountId = customer.AccountId
GROUP BY CompanyAccountId
ORDER BY CASE WHEN CompanyAccountId IN (SELECT AccountId 
                                          FROM customer
                                          WHERE customerid= p_CustomerId) 
                 THEN 0
                 ELSE 1
          END, CompanyName;

Opis: Chcę pokazać listę kont. Tutaj przekazuję identyfikator klienta w sp. Teraz wyświetli listę nazw rachunków z kontami połączonymi z tymi klientami, które są wyświetlane u góry, a następnie inne konta w kolejności alfabetycznej.

Hun
źródło
2

Potrzebujesz kolejnej kolumny (numerycznej) w swojej tabeli, w której określisz porządek sortowania. Klauzula IN nie działa w ten sposób.

B - 1
A - 2
D - 3
E - 4
C - 5
Robert Harvey
źródło
2
Pożądana kolejność może dotyczyć zapytania.
Vladimir Dyuzhev
0

po prostu użyj

order by INSTR( ',B,C,D,A,' ,  concat(',' , `field`, ',' ) )

unikaj takiej sytuacji

 INSTR('1,2,3,11' ,`field`) 

zakończy się nieuporządkowanym wierszem wyniku: alternatywa 1 i 11

PercyQQ
źródło