What if I want to search for a single row in a table with a decrementing precision, e.g. like this:
SELECT * FROM image WHERE name LIKE 'text' AND group_id = 10 LIMIT 1
When this gives me no result, try this one:
SELECT * FROM image WHERE name LIKE 'text' LIMIT 1
And when this gives me no result, try this one:
SELECT * FROM image WHERE group_id = 10 LIMIT 1
Is it possible to do that with just one expression?
Also there arises a problem when I have not two but e.g. three or more search parameters. Is there a generic solution for that? Of course it would come in handy when the search result is sorted by its relevance.
LIKE
without wildcard character is equivalent to=
. Assuming you actually meantname = 'text'
.Indexes are the key to performance.
Test setup
Ideally, you create two indexes (in addition to the primary key):
The second may not be necessary, depending on data distribution and other details. Explanation here:
Query
This should be the fastest possible query for your case:
SQL Fiddle.
The
LIMIT
clause applies to the whole query. Postgres is smart enough not to execute later legs of theUNION ALL
as soon as it has found enough rows to satisfy theLIMIT
. Consequently, for a match in the firstSELECT
of the query, the output ofEXPLAIN ANALYZE
looks like this (scroll to the right!):Bold emphasis mine.
Do not add an
ORDER BY
clause, this would void the effect. Then Postgres would have to consider all rows before returning the top row.Final questions
This is the generic solution. Add as many
SELECT
statements as you want.There is only one row in the result with
LIMIT 1
. Kind of voids sorting.It's late and I don't feel like writing out a full solution, but if I needed this I would probably create a customer function that returned a customer type, record or a table (depending on what your needs are). The advantage to this would be that once you found your record, you could stop.
Making the number of params be dynamic will make it a bit more challenging. Depending on your version of PostgreSQL (and the extension available to you), you might be able to pass in an hstore or json and dynamically build the query.
Maybe not the greatest SO answer, but it's more than a comment and hopefully some food for thought.
This would be a pseudo-solution approach but I'm not entirely sure if the syntax in your scenario would allow for it
I don't think there is anything wrong with running these queries separately until you find the result you want. While there are ways to combine these into one query, those end up being more complicated and slower, which isn't what you wanted.
You should run consider running all of the queries in one transaction, probably best in repeatable-read isolation level, so you get consistent results and also avoid the overhead of setting up repeated transactions. If in addition you make judicious use of prepared statements, you will have almost the same overhead as running all three queries in one combined statement.