Reputation: 934
Suppose I have a table foo
from which I'd like to select N rows from each category
create table foo(name text, category text);
name | category
------+----------
aaa | cat1
bbb | cat1
ccc | cat2
ddd | cat2
eee | cat2
Now I'd like to pick from foo given a number of categories
category | count
----------+-------
cat2 | 2
cat1 | 1
The result should be 3 rows (ties could be resolved randomly or by any order)
name
------
ccc
ddd
aaa
-- wrong, not taking counts into account
with t as (select * from (values ('cat1', 1), ('cat2', 2)) as
t(category, count)) select name from foo, t where foo.category = t.category;
name
------
aaa
bbb
ccc
ddd
eee
I could do this with multiple queries, but I think I am missing something very obvious and the select can be done with a single query.
Upvotes: 1
Views: 72
Reputation: 36127
SELECT x.*
FROM categories c,
LATERAL (
select * FROM foo
where foo.category = c.category
ORDER BY random()
LIMIT c.count
) x
Demo: http://sqlfiddle.com/#!17/e0f14/7
Upvotes: 3
Reputation: 1270773
You would use row_number()
:
select foo.*
from (select t.*,
row_number() over (partition by foo.category order by foo.category) as seqnum
from foo join
t
on foo.category = t.category
) t
where seqnum <= t.cnt;
Upvotes: 1