É possível que haja momentos em que uma ordem específica é requerida em uma consulta SQL, o que não pode ser feito usando ASC ou DESC ou usando um campo de ordenação especial. MySQL tem uma função ORDER BY FIELD que pode ser usada para fazer isto.
Example Data
Os dados de exemplo neste post usam a minha tabela de frutas de exemplo. Esta é uma tabela um pouco simples mas pode ser usada para ilustrar o ponto neste post muito bem.
Encomenda por valores de campo específicos
A tabela de frutas tem um campo “nome” com os seguintes valores únicos: Maçã, Banana, Laranja, Pêra. Cada um destes valores únicos tem um conjunto de variedades.
Vamos dizer, por exemplo, que queremos ordenar os dados numa ordem específica por Banana, Maçã, Pêra, Laranja e depois pelas suas variedades. Não é possível fazer isso usando uma cláusula regular ORDER BY porque uma ordem ascendente ou descendente neste campo não vai funcionar. Nós precisaríamos de alguma forma de ordenação por coluna ou outra alternativa.
Usando a função FIELD( ) na cláusula ORDER BY podemos conseguir isso. Ele funciona especificando a coluna a ordenar por e depois os valores a ordenar por ordem. Por exemplo:
SELECT * FROM fruit ORDER BY FIELD(name, 'Banana', 'Apple', 'Pear', 'Orange'), variety;
Os dados resultantes da tabela de exemplo parecem-se com isto:
+----------+--------+---------------------+| fruit_id | name | variety |+----------+--------+---------------------+| 11 | Banana | Burro || 12 | Banana | Cavendish || 10 | Banana | Plantain || 6 | Apple | Cox's Orange Pippin || 7 | Apple | Granny Smith || 1 | Apple | Red Delicious || 8 | Pear | Anjou || 4 | Pear | Bartlett || 2 | Pear | Comice || 5 | Orange | Blood || 3 | Orange | Navel || 9 | Orange | Valencia |+----------+--------+---------------------+
The gotcha
Existe um pequeno “gotcha” quando se usa esta função. Quaisquer valores que estejam na coluna que não estejam na função FIELD() aparecerão em uma ordem mais ou menos aleatória antes dos valores especificados. Por exemplo, especificando apenas Apple e Banana:
SELECT * FROM fruit ORDER BY FIELD(name, 'Banana', 'Apple') DESC, variety;
Resulta em:
+----------+--------+---------------------+| fruit_id | name | variety |+----------+--------+---------------------+| 6 | Apple | Cox's Orange Pippin || 7 | Apple | Granny Smith || 1 | Apple | Red Delicious || 11 | Banana | Burro || 12 | Banana | Cavendish || 10 | Banana | Plantain || 8 | Pear | Anjou || 4 | Pear | Bartlett || 5 | Orange | Blood || 2 | Pear | Comice || 3 | Orange | Navel || 9 | Orange | Valencia |+----------+--------+---------------------+
Uma solução para o gotcha
Apesar de normalmente só utilizar esta função quando as colunas exactas são conhecidas, uma solução é inverter a ordem dos campos especificados e ordená-los numa ordem decrescente, e depois fazer uma segunda ordenação no mesmo campo.
O exemplo seguinte, apesar da aparência, na verdade ordena em ordem de Banana, depois Apple, e depois os outros nomes em ordem ascendente:
SELECT * FROM fruit ORDER BY FIELD(name, 'Apple', 'Banana') DESC, name, variety;
Este resultado em:
+----------+--------+---------------------+| fruit_id | name | variety |+----------+--------+---------------------+| 11 | Banana | Burro || 12 | Banana | Cavendish || 10 | Banana | Plantain || 6 | Apple | Cox's Orange Pippin || 7 | Apple | Granny Smith || 1 | Apple | Red Delicious || 5 | Orange | Blood || 3 | Orange | Navel || 9 | Orange | Valencia || 8 | Pear | Anjou || 4 | Pear | Bartlett || 2 | Pear | Comice |+----------+--------+---------------------+
Esta pode ser uma solução útil se um conjunto específico de linhas precisar aparecer antes dos outros no conjunto de resultados, mas normalmente não apareceria primeiro quando se usa uma ordem de ordenação ASC ou DESC.