How to do an exact match followed by ORDER BY in PostgreSQL
Asked Answered
H

2

6

I'm trying to write a query that puts some results (in my case a single result) at the top, and then sorts the rest. I have yet to find a PostgreSQL solution.

Say I have a table called airports like so.

 id | code |        display_name         
----+------+----------------------------
  1 | SDF  | International               
  2 | INT  | International Airport       
  3 | TES  | Test                        
  4 | APP  | Airport Place International

In short, I have a query in a controller method that gets called asynchronously when a user text searches for an airport either by code or display_name. However, when a user types in an input that matches a code exactly (airport code is unique), I want that result to appear first, and all airports that also have int in their display_name to be displayed afterwards in ascending order. If there is no exact match, it should return any wildcard matches sorted by display_name ascending. So if a user types in INT, The row (2, INT, International Airport) should be returned first followed by the others:

Results:
1. INT | International Airport
2. APP | Airport Place International
3. SDF | International

Here's the kind of query I was tinkering with that is slightly simplified to make sense outside the context of my application but same concept nonetheless.

SELECT * FROM airports
WHERE display_name LIKE 'somesearchtext%'
ORDER BY (CASE WHEN a.code = 'somesearchtext` THEN a.code ELSE a.display_name END)

Right now the results if I type INT I'm getting

Results:
1. APP | Airport Place International
2. INT | International Airport
3. SDF | International

My ORDER BY must be incorrect but I can't seem to get it Any help would be greatly appreciated :)

Heaton answered 31/7, 2017 at 14:18 Comment(0)
P
11

If you want an exact match on code to return first, then I think this does the trick:

SELECT a.*
FROM airports a
WHERE a.display_name LIKE 'somesearchtext%'
ORDER BY (CASE WHEN a.code = 'somesearchtext' THEN 1 ELSE 2 END),
         a.display_name

You could also write this as:

ORDER BY (a.code = 'somesearchtext') DESC, a.display_name

This isn't standard SQL, but it is quite readable.

Pt answered 31/7, 2017 at 14:20 Comment(2)
Note you don't need the CASE. Since "=" returns a boolean and TRUE sorts after FALSE, you can do "ORDER BY a.code='yourvalue' DESC, a.display_name"East
ORDER BY (a.code != 'somesearchtext') also works.Jud
R
0

I think you can achieve your goal by using a UNION. First get an exact match and then add that result to rest of the data as you which.

e.g.. (you will need to work in this a bit)

SELECT * FROM airports
WHERE code == 'somesearchtext'
ORDER BY display_name 

UNION

SELECT * FROM airports
WHERE code != 'somesearchtext' AND display_name LIKE 'somesearchtext%'
ORDER BY display_name 
Rapacious answered 31/7, 2017 at 14:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.