MySQL - valores ORDER BY dentro de IN ()


107

Espero classificar os itens retornados na consulta a seguir pela ordem em que foram inseridos na função IN () .

ENTRADA:

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

RESULTADO:

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

Alguma ideia?

Respostas:


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

A função FIELD retorna a posição da primeira string na lista de strings restante.

No entanto, é muito melhor em termos de desempenho ter uma coluna indexada que representa sua ordem de classificação e, em seguida, classificar por esta coluna.


9
@Vladimir - sim, é específico do MySQL. A questão tem a tag mysql.
Ayman Hourieh

Ótimo, substituto para a função de "decodificação" do Oracle após a troca de banco de dados.
Martin Lyne

7
Cuidado. Qualquer valor de propriedade desconhecido (não na lista) terá precedência sobre os valores conhecidos, ou seja FIELD(letter, 'A', 'C'), a lista retornará primeiro as entradas com a letra B primeiro (assumindo um conjunto de registros com A | B | Cvalores). Para evitar isso, inverta a lista e use DESC, ie FIELD(letter, 'C', 'A') DESC.
Gajus

Como faço para fazer isso no servidor SQL.
user123456

29

Outra opção aqui: 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;

Portanto, no seu caso (não testado) seria

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';

Dependendo do que você está fazendo, eu achei um pouco peculiar, mas sempre consegui trabalhar depois de brincar um pouco com ele.


Isso pode ser melhor do que usar a função field () como outra resposta sugerida porque o uso de field () impedirá o uso do índice, mas ele tem uma chance de usar um índice usando este método (não tenho certeza de quão bem ele pode usar o índice, no entanto)
ʞɔıu


3

Pode ser que isso possa ajudar alguém (p_CustomerId é passado em 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;

Descrição: desejo mostrar a lista de contas. Aqui estou passando um id de cliente em sp. Agora, ele listará os nomes das contas com contas vinculadas a que os clientes são mostrados no topo, seguidos por outras contas em ordem alfabética.


2

Você precisa de outra coluna (numérica) em sua tabela, na qual especifica a ordem de classificação. A cláusula IN não funciona dessa maneira.

B - 1
A - 2
D - 3
E - 4
C - 5

2
A ordem desejada pode ser por consulta.
Vladimir Dyuzhev

0

Apenas use

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

evite a situação como

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

terminará com linha de resultado não ordenado: 1 e 11 alternantes

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.