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 ?
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With