2012-02-21 15 views
88

En MySQL, ¿cómo puedo definir una orden de clasificación personalizada?Cómo definir una orden ORDER BY personalizada en mySQL

para tratar de explicar lo que quiero considerar esta tabla:

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

aquí quiero devolver todos los registros ordenados por idioma y el ID ascendente de manera que Language = ENU viene primero, luego JPN y por último DAN.

El resultado debe ser: A, D, B, E, C, F, etc.

Es esto posible?

Respuesta

195

MySQL tiene una función práctica llamada FIELD() que es excelente para tareas como esta. Sin embargo

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

Nota, que

  1. que hace que su SQL menos portátiles, como otros DBMS que no tenga tal función

  2. Cuando su lista de idiomas (u otros valores de ordenar por) obtiene mucho más tiempo, es mejor tener una tabla separada con la columna ordenar por ordenar para ellos y unirlo a sus consultas para ordenar.

+2

Gracias, esto es perfecto para mi situación en la que solo tengo que ordenar por dos valores (un idioma principal, por ejemplo, JPN, y un idioma alternativo, por ejemplo, ENU). – Muleskinner

+1

Hombre me acabas de guardar una reescritura en magento :) –

+1

¿Qué pasa si tienes un 'GROUP BY' antes? Por ejemplo, el primer valor que quiero, aparece al final? – Pathros

31

Si esas son las únicas tres valores, a continuación, puede utilizar a CASE expression:

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

(Si pudiera haber otros valores, entonces es posible que desee añadir un poco de lógica adicional para mantener el orden coherente, por ejemplo, , es posible añadir a ELSE 4 que CASE expresión, y luego por fin Language como el tercer criterio de ordenación:

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

Y si hay muchos valores idioma que podría haber una mesa separada almacenar cada idioma además de una columna de orden de clasificación y enlace a ese – kaj

+0

Esto ordenar por ID en primer lugar, lo que resulta en a, b, c, d, e , f – piotrm

+0

Gracias, esto funciona a la perfección, al igual que Mchl, respuesta que acepté, ya que parece más simple – Muleskinner

13

usted tiene un par de opciones de la mano torpe, la primera es para cambiar de idioma ser ENUM (suponiendo que esto sea posible, y solo espera algunas variaciones)

Si lo especifica como ENUM('ENU','JPN','DAN'), entonces ORDER Language ASC ordenará en el orden que usted especifique.

La segunda consistirá en un caso en alguna parte, es decir,

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 

En cuanto al rendimiento del método ENUM proporcione resultados más rápidos, pero será más molesto si es necesario agregar más idiomas. Una tercera opción sería agregar una tabla de normalización para los Idiomas, sin embargo, puede ser exagerado en esta instancia.

+0

¿Dónde exactamente escribe 'ENUM ('ENU', 'JPN', 'DAN')'? – Pathros

+1

@pathros en la definición de la tabla, lo especifica como ENUM en lugar de VARCHAR, etc.Internamente, MySQL almacena las opciones ENUM en un orden específico y las indexa, por lo que cuando ordena por una columna ENUM específicamente usará ese índice interno en lugar de los valores de cadena (a menos que CAST() se use para regresar a un VARCHAR) –

+0

¿No debería 'END DESC', ser 'END CASE DESC,'? –