Puede haber ocasiones en las que se requiera un orden específico en una consulta SQL que no pueda realizarse utilizando ASC o DESC o utilizando un campo de ordenación especial. MySQL tiene una función ORDER BY FIELD que se puede utilizar para hacer esto.
Datos de ejemplo
Los datos de ejemplo en este post utilizan mi tabla de frutas de ejemplo. Se trata de una tabla algo simple, pero se puede utilizar para ilustrar el punto en este post bastante bien.
Ordenación por valores de campo específicos
La tabla de frutas tiene un campo «nombre» con los siguientes valores únicos: Manzana, Plátano, Naranja, Pera. Cada uno de estos valores únicos tiene un conjunto de variedades.
Digamos, para argumentar, que queremos ordenar los datos en un orden específico por Plátano, Manzana, Pera, Naranja y luego por sus variedades. No es posible hacer esto utilizando una cláusula ORDER BY normal porque una ordenación ascendente o descendente en este campo no funcionará. Necesitaríamos algún tipo de columna de ordenación u otra alternativa.
Usando la función FIELD( ) en la cláusula ORDER BY podemos conseguirlo. Funciona especificando la columna por la que se va a ordenar y luego los valores que se van a ordenar. Por ejemplo:
SELECT * FROM fruit ORDER BY FIELD(name, 'Banana', 'Apple', 'Pear', 'Orange'), variety;
Los datos resultantes de la tabla de ejemplo tienen el siguiente aspecto:
+----------+--------+---------------------+| 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 |+----------+--------+---------------------+
El inconveniente
Hay un pequeño «inconveniente» al utilizar esta función. Cualquier valor que esté en la columna que no esté en la función FIELD() aparecerá en un orden más o menos aleatorio antes de los valores especificados. Por ejemplo, especificando sólo Apple y Banana:
SELECT * FROM fruit ORDER BY FIELD(name, 'Banana', 'Apple') DESC, variety;
Esto resulta en:
+----------+--------+---------------------+| 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 |+----------+--------+---------------------+
Una solución al gotcha
Aunque normalmente sólo se utilizaría esta función cuando se conocen las columnas exactas, una solución es invertir el orden de los campos especificados y ordenarlos de forma descendente, y luego hacer una segunda ordenación en el mismo campo.
El siguiente ejemplo, a pesar de su apariencia, en realidad ordena en orden de Plátano, luego de Manzana, y luego los otros nombres en orden ascendente:
SELECT * FROM fruit ORDER BY FIELD(name, 'Apple', 'Banana') DESC, name, variety;
Esto resulta en:
+----------+--------+---------------------+| 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 puede ser una solución útil si un conjunto específico de filas necesita aparecer antes que los demás en el conjunto de resultados, pero normalmente no aparecería primero cuando se utiliza un orden ASC o DESC.