Вы не упоминаете, какую MySQL версию вы используете, поэтому я предполагаю, что это MySQL 8.x.
В MySQL 8.x вы можете использовать функцию DENSE_RANK()
определить строки, которые вы хотите. Тогда простой предикат удалит те, которые вам не нужны.
Например, если мы хотим ограничить до 2 строк b
для каждого a
(независимо от строк в c
), Вы можете сделать:
select *
from (
select
a.id,
b.id as bid,
dense_rank() over(partition by a.id order by b.id) as drank,
c.id as cid
from a
left join b on b.aid = a.id
left join c on c.bid = b.id
) x
where drank <= 2
Результат:
id bid drank cid
-- --- ----- ------
1 11 1 100
1 11 1 101
1 11 1 102
1 11 1 103
1 12 2 120
2 20 1 200
2 20 1 201
2 21 2 202
3 30 1 <null>
Как видите, он показывает только 11
и 12
для идентификатора = 1, хотя всего их 5 строки для него (все пять имеют ранг 1 и 2). Вы можете увидеть запущенный пример на DB Fiddle . Сценарий данных для этого примера:
create table a (id int primary key not null);
insert into a (id) values (1), (2), (3);
create table b (id int primary key not null, aid int references a (id));
insert into b (id, aid) values
(11, 1), (12, 1), (13, 1), (14, 1),
(20, 2), (21, 2),
(30, 3);
create table c (id int primary key not null, bid int references b (id));
insert into c (id, bid) values
(100, 11), (101, 11), (102, 11), (103, 11),
(120, 12), (130, 13), (140, 14),
(200, 20), (201, 20),
(202, 21);