Ordenar por el orden de los valores en una cláusula SQL IN()

Resuelto Darryl Hein asked hace 15 años • 13 respuestas

Me pregunto si existe una forma (posiblemente una mejor manera) de ordenar según el orden de los valores en una cláusula IN().

El problema es que tengo 2 consultas, una que obtiene todos los ID y la segunda que recupera toda la información. El primero crea el orden de las ID por las que quiero que ordene el segundo. Los ID se colocan en una cláusula IN() en el orden correcto.

Entonces sería algo como (extremadamente simplificado):

SELECT id FROM table1 WHERE ... ORDER BY display_order, name

SELECT name, description, ... WHERE id IN ([id's from first])

El problema es que la segunda consulta no devuelve los resultados en el mismo orden en que se colocan los ID en la cláusula IN().

Una solución que encontré es colocar todos los ID en una tabla temporal con un campo de incremento automático que luego se une a la segunda consulta.

¿Hay alguna opción mejor?

Nota: Como la primera consulta la ejecuta "el usuario" y la segunda se ejecuta en un proceso en segundo plano, no hay forma de combinar la consulta 2 en 1 mediante subconsultas.

Estoy usando MySQL, pero creo que podría ser útil anotar qué opciones hay para otras bases de datos también.

Darryl Hein avatar Dec 29 '08 05:12 Darryl Hein
Aceptado

Utilice la función de MySQL FIELD():

SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])

FIELD()devolverá el índice del primer parámetro que es igual al primer parámetro (que no sea el primer parámetro en sí).

FIELD('a', 'a', 'b', 'c')

regresará 1

FIELD('a', 'c', 'b', 'a')

regresará 3

Esto hará exactamente lo que desea si pega los identificadores en la IN()cláusula y la FIELD()función en el mismo orden.

ʞɔıu avatar Dec 28 '2008 22:12 ʞɔıu

Vea a continuación cómo obtener datos ordenados.

SELECT ...
  FROM ...
 WHERE zip IN (91709,92886,92807,...,91356)
   AND user.status=1
ORDER 
    BY provider.package_id DESC 
     , FIELD(zip,91709,92886,92807,...,91356)
LIMIT 10
Pradeep Singh avatar Dec 01 '2011 09:12 Pradeep Singh

Dos soluciones que me vienen a la mente:

  1. order by case id when 123 then 1 when 456 then 2 else null end asc

  2. order by instr(','||id||',',',123,456,') asc

( instr()es de Oracle; tal vez tengas locate()o charindex()algo así)

John Nilsson avatar Dec 28 '2008 23:12 John Nilsson