You can do this with a single SQL statement. I'm not sure whether you'll be able to avoid a table scan. You might need to include some more columns, depending most likely on whether you need to sort by them.
select *
from (select
id, title, content,
row_number() over (partition by type order by create_date asc) row_num
from portal
) as numbered_rows
where row_num <= 5;
One advantage of this kind of SQL statement is that it requires no maintenance. It will continue to work correctly no matter how many different types you add.
Think carefully whether you need the first five (order by create_date ASC
) or the latest five (order by create_date DESC
).