how to make sure a record is always at the top in a given resultset in mysql?

这一生的挚爱 提交于 2019-12-22 04:44:34

问题


I have a search query which yields a resultset based on input parameters and the result can be sorted (ASC/DESC) based on different parameters: price, duration etc (with pagination in place and limit of 10 records)

I now have a requirement wherein, if I have an id passed in, I'd like the corresponding record to be made to sticky at the top in the given resultset.

Lets say we have a package table like this:

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"

Let's assume the complete resultset is 20 records with ids 1 to 20. I'm now required to return record with id 14 to always be at the top. I came up with the following query, but this isn't working:

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"

My guess as to why this is not working: After order by clause, the resultset is sorted in descending order, which is then truncated at 10 records. The record with id=14 may not be a part of this truncated set. Is this correct ?

How do I get record with id=14 to stick at the top ?


回答1:


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

p.id=14 returns 1 if the condition is true, 0 otherwise, so sorting descending brings the desired row to the top.

Returning a number from a comparison is a MySQL feature, with standard SQL you would write:

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

I find this easier to read than the UNION, and it might perform better.




回答2:


Use a union to always have your package at top:

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



回答3:


try this:

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

Instead of (select MAX(p.mPrice)+1 from package ) you can give a constant value which would be always a maximun value, something like this

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

which would be more effitient



来源:https://stackoverflow.com/questions/11823689/how-to-make-sure-a-record-is-always-at-the-top-in-a-given-resultset-in-mysql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!