2012-08-06 12 views
6

que tienen una consulta de búsqueda que proporciona un conjunto de resultados sobre la base de parámetros de entrada y el resultado puede ser ordenada (ASC/DESC) en base a diferentes parámetros: precio, duración, etc (con paginación en su lugar y límite de 10 registros)cómo asegurarse de que un registro esté siempre en la parte superior de un determinado conjunto de resultados en mysql?

Ahora tengo un requisito en el que, si tengo un id aprobado, me gustaría que el registro correspondiente se convierta en adhesivo en la parte superior del conjunto de resultados.

digamos que tenemos una mesa paquete de la siguiente manera:

Package 
- id 
- name 
- mPrice 
- vPrice 
- duration 

// Searching pkg based on Price (in DESC order) where name = Thailand 
sqlQuery = 
"SELECT p.id, p.name, p.mPrice, p.vPrice FROM package p 
WHERE p.name = LOWER('Thailand') 
ORDER BY (p.mPrice + p.vPrice) DESC 
LIMIT 10" 

Vamos a suponer que el conjunto de resultados completa es de 20 registros con identificadores de 1 a 20. Ahora estoy obligado a devolver registro con id 14 para estar siempre a la parte superior. Se me ocurrió la siguiente consulta, pero esto no está funcionando:

sqlQuery = 
"SELECT p.id, p.name, p.mPrice, p.vPrice FROM package p 
WHERE p.name = LOWER('Thailand') or p.id = 14 
ORDER BY CASE 
WHEN p.id=14 then 0 
else (p.mPrice + p.vPrice) 
end DESC 
LIMIT 10" 

Mi conjetura en cuanto a por qué esto no está funcionando: Después de la cláusula ORDER BY, el conjunto de resultados se ordena en orden descendente, que se trunca después a 10 registros. El registro con id = 14 puede no ser parte de este conjunto truncado. Es esto correcto ?

¿Cómo obtengo el registro con id = 14 para pegarme en la parte superior?

Respuesta

16
ORDER BY (p.id=14) DESC, (p.mPrice=p.vPrice) DESC 

p.id=14 rendimientos 1 si la condición es verdadera, 0 de otro modo, por lo que la clasificación descendente trae la fila deseada para la parte superior.

Volviendo un número de una comparación es una característica de MySQL, SQL estándar con usted escribiría:

ORDER BY CASE WHEN (p.id=14) THEN 0 ELSE 1 END, 
     CASE WHEN (p.mPrice=p.vPrice) THEN 0 ELSE 1 END 

Me parece más fácil de leer que el UNION, y funcionará mucho mejor.

+0

¡Muy bueno! Debería haber pensado en esto. Sin embargo, esto no funcionó cuando traté de ordenarlo con ASC y no estoy seguro de por qué. 'ORDER BY (p.id = 14) ASC, (p.mPrice = p.vPrice) ASC' – brainydexter

+1

' p.id = 14' devuelve '1' si la condición es verdadera,' 0' en caso contrario. La ordenación ascendente pone el '0' primero, por lo que el que desea es el último ... –

+0

¡Ajá! Estupendo. Simplemente cambiaré el operador de igualdad a la identificación basada en ASC/DESC. ¿Tiene alguna idea de si esto podría funcionar mejor que UNION? – brainydexter

2

Utilice una unión para tener siempre su paquete en la parte superior:

SELECT id, name, mPrice, vPrice FROM package WHERE id = 14 
UNION 
SELECT p.id, p.name, p.mPrice, p.vPrice FROM package p 
WHERE p.name = LOWER('Thailand') or p.id = 14 
ORDER BY (p.mPrice = p.vPrice) DESC 
LIMIT 9 
+2

'UNION ALL' es más rápido que el funcionamiento de' UNION'. – Omesh

+0

Pero no desea tener la identificación 14 en la parte superior y una vez más en el "cuerpo" – Matten

0

probar esto:

order by 
case when p.id=14 then then (select MAX(mPrice)+1 from package) else 
(p.mPrice = p.vPrice) end desc 
LIMIT 10 

En lugar de (SELECT MAX (p.mPrice) 1 de paquete) que puede dar un valor constante que sería siempre un valor máximo, algo como esto

order by 
case when p.id=14 then then 1000000 else 
(p.mPrice = p.vPrice) end desc 
LIMIT 10 

que sería más effitient

+0

¿Puede explicar qué está haciendo en esa expresión? – brainydexter

+0

@brainydexter: Solo estoy obteniendo el valor máximo + 1 por precio, por lo que siempre estará en la parte superior –

Cuestiones relacionadas