You can add LIMIT 1
, but LIMIT
is applied after aggregation (so after the count). Adding it in the same query level does nothing useful, since there is only 1 row left to return anyway: the row count. Would be misleading nonsense.
If you want to go that route, add LIMIT
in a subquery and count in the outer SELECT
, like:
SELECT count(*) FROM (
SELECT -- empty SELECT list
FROM submission
JOIN ...
WHERE ...
LIMIT 1
) sub
For this special purpose it's fastest to leave the SELECT
list empty. count(*)
only counts the existence of rows without regard to any columns.
You can do that with any LIMIT
, really. To check whether there are at least N rows. See:
Checking for N = 1 is just your special case. And while we only care whether any rows exist and not how many, EXISTS
is the better, faster tool:
SELECT EXISTS (
SELECT FROM submission s
JOIN post p ON s.id = p.submission_id
WHERE s.user_name = ?
AND p.tag ~* 'verified'
AND NOT p.tag ~* 'unverified'
);
Without index, lower(col) LIKE '%something%'
is a bit faster than col ~* 'something'
. But if your tables are big and performance matters (like your question indicates), you should have matching indexes to begin with, a trigram index on tag
to be precise. Assuming tag is from table post
(you left room for interpretation there):
CREATE INDEX post_tag_gin_trgm_idx ON post USING gin (tag gin_trgm_ops);
Then the simpler expression is just as fast. See:
Depending on cardinalities and data distribution it might make sense to combine that with submission_id
in a multicolumn index:
CREATE INDEX post_foo_trgm_idx ON post USING gin (submission_id, tag gin_trgm_ops);
You'd need the additional module btree_gin for that. See:
And it might make sense to have another multicolumn index on submission(id, user_name)
- or on submission(user_name, id)
, again depending on the mentioned details. The first variant is more likely to be useful in case Postgres expects the predicate on submission.user_name
to be more selective.
(Your handling of tags might be optimized further.)
Aside:
If the result is greater than 0 I do something in my application for this user.
If that something is another SQL DML statement, make it a single statement for additional gains. Example:
UPDATE foo
SET bar = 'baz'
WHERE EXISTS ( ...) -- like above
AND bar IS DISTINCT FROM 'baz' -- avoid empty updates
About the added last line:
Or you embed the expression in plpgsql code for procedural needs, like demonstrated here:
submission.user_name
, or the join would be odd.