SELECT id, title, description, "source", category, published_on
FROM (
SELECT *, rank() OVER (PARTITION BY "source" ORDER BY category, published_on DESC)
FROM news
WHERE category IN ('c1', 'c2')
) t
WHERE rank < 6
UNION
SELECT *
FROM news
WHERE category NOT IN ('c1', 'c2')