Assume the following table records:
TABLE: foo
==========================
| foo_id | foo_parent_id |
==========================
| 1 | NULL |
|
I'd like to offer another approach at answering this question:
SET @topN = 1;
SELECT foo_id, foo_parent_id
FROM (
SELECT
f.foo_id
, f.foo_parent_id
, IFNULL(f.foo_parent_id, f.foo_id) AS grp_rank
, CASE
WHEN f.foo_parent_id IS NULL
THEN @topN:= 1
ELSE
@topN:=@topN+1
END topN_rank
, f_parent.foo_id AS f_parent_foo_id
FROM
foo AS f
RIGHT JOIN (
SELECT foo_id
FROM foo
WHERE foo_parent_id IS NULL
ORDER BY foo_id LIMIT 10
) f_parent
ON f_parent.foo_id = IFNULL(f.foo_parent_id, f.foo_id)
ORDER BY grp_rank, f.foo_id
) AS foo_derived
WHERE topN_rank <= 3
General Notes:
I want to get, say, the first 10 parent records <-- SUBQUERY "f_parent"
followed by, say, the first 2 child records of that parent record. <-- topN <= 3 (PARENT + 2 CHILDREN)
How it works:
grp_rankNULL foo_parent_id resets the ranking. This new column topN_rank is impacted by the sorting. topN_rank and to return only the needed columns.topN_rank column to get the top N rows for each group, prohibiting more than 3 per group.