Reputation: 26245
Let's say I have a simple schema of two tables, users
and posts
. The posts
table has a foreign key to users
indicating who authored the post.
Also, let's say I want to list the users and their 3 most-recent posts. I can do this in O(n) queries (1 to list users, 1 for each user getting their posts), but how would I do this in O(1) queries?
Either one query to get the users and posts all at once, or 2 queries, one to get the users and one to get the posts. Assume I would de-dupe any repeated user data.
Upvotes: 2
Views: 960
Reputation: 32392
A self join that should work on most db's. This assumes that post_time
is unique per user. If that's not the case, then you can replace on p2.post_time >= p.post_time
with on p2.id >= p.id
.
select u.username, p.id, p.title
from user u join
(
select p.id, p.title, p.user_id
from posts p join posts p2
on p2.user_id = p.user_id
and p2.post_time >= p.post_time
group by p.id, p.title, p.user_id
having count(*) <= 3
) p on u.id = p.user_id
Upvotes: 1
Reputation: 13248
The following should work in any database:
select u.username, p.title, p.post_time
from users u
join posts p
on u.id = p.user_id
where p.post_time >=
(select max(z.post_time)
from posts z
where z.user_id = p.user_id
and z.post_time <
(select max(y.post_time)
from posts y
where y.user_id = p.user_id
and y.post_time <
(select max(x.post_time)
from posts x
where x.user_id = p.user_id)))
Upvotes: 1
Reputation: 119
SELECT *
FROM Users a
CROSS APPLY (
SELECT TOP 3 *
FROM posts z
WHERE a.User_ID = z.User_ID
ORDER BY z.post_time DESC
) b
Upvotes: 0
Reputation:
You didn't state your DBMS, so this is ANSI SQL (supported by a wide range of DBMS):
select *
from (
select u.username,
p.title,
row_number() over (partition by u.id order by p.post_time desc) as rn
from users u
join posts p on u.id = p.user_id
) t
where rn <= 3
order by u.username;
Upvotes: 5