This is probably fastest:
SELECT u.*
FROM usr u -- avoiding "User" as table name
JOIN LATERAL (
SELECT name
FROM userevent
WHERE user_id = u.id
ORDER BY date DESC NULLS LAST
LIMIT 1
) ue ON ue.name = 'played';
LATERAL
requires Postgres 9.3+:
Or you could use DISTINCT ON
(faster for few rows per user):
SELECT u.*
FROM usr u -- avoiding "User" as table name
JOIN (
SELECT DISTINCT ON (user_id)
user_id, name
FROM userevent
ORDER BY user_id, date DESC NULLS LAST
) ue ON ue.user_id = u.id
AND ue.name = 'played';
Details for DISTINCT ON
:
SQL Fiddle with valid test case.
If date
is defined NOT NULL
, you don't need NULLS LAST
. (Neither in the index below.)
Key to read performance for both but especially the first query is a matching multicolumn index:
CREATE INDEX userevent_foo_idx ON userevent (user_id, date DESC NULLS LAST, name);
Aside: Never use reserved words as identifiers.