Ordenar por el orden de los valores en una cláusula SQL IN()
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.
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.
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
Dos soluciones que me vienen a la mente:
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
( instr()
es de Oracle; tal vez tengas locate()
o charindex()
algo así)