Получить количество связанных строк в postgres с существующим боковым соединением - PullRequest
0 голосов
/ 27 апреля 2020

Этот запрос дает мне несколько строк из table1 вместе со связанными записями из table2 с использованием left join lateral. Я ограничил строки от таблицы 2 до 10 строк каждая.

select t1.id, array_agg(t2.column1) 
from table1 t1 
left join lateral (select * from table2 where table1_id = t1.id order by column2 limit 10) t2 on true 
where t1.other = other_value
group by t1.id

Но как я могу включить общее количество count(*) всех записей в таблице2, связанных с таблицей1 (select count(*) from table2 where table1_id = t1.id). Поскольку я выполняю боковое соединение, я не уверен, как бы я добавил эти результаты.

Могу ли я повторно использовать боковое соединение, которое я уже делаю, или мне нужно было бы сделать отдельное боковое соединение, потому что первый имеет limit 10, а count(*) не требует ограничений? Как должен выглядеть запрос, чтобы он работал следующим образом? (Я думаю, что мог бы быть способ сделать это, используя синтаксис среза массива из первого бокового соединения, но я думаю, что это было бы дорого, поскольку ему нужно было бы получить все строки только для подсчета их числа.)

1 Ответ

1 голос
/ 27 апреля 2020

Вы можете также использовать оконные функции для этого:

select t1.id, array_agg(t2.column1) 
from table1 t1 left join
     (select t2.*, count(*) over (partition by table1_id) as cnt,
             row_number() over (partition by table1_id order by column2) as seqnum
      from table2
     ) t2
     on t2.table1_id = t1.id and sequm <= 10
where t1.other = other_value 
group by t1.id;

Вы можете сделать это как отдельный lateral join.

РЕДАКТИРОВАТЬ:

С отдельным боковое соединение:

select t1.id, array_agg(t2.column1), t2c.cnt
from table1 t1 left join lateral
     (select *
      from table2
      where table1_id = t1.id
      order by column2
      limit 10
     ) t2
     on true left join lateral
     (select count(*) as cnt
      from table2
      where table1_id = t1.id
     ) t2c
     on true
where t1.other = other_value
group by t1.id, t2.cnt;

Или с одним боковым соединением без агрегации во внешнем запросе:

select t1.id, t2.column1s, t2.cnt
from table1 t1 left join lateral
     (select array_agg(t2.column1) as column1, max(cnt) as cnt
      from (select t2.*,
                   row_number() over (order by column2 desc) as seqnum,
                   count(*) over () as cnt
            from table2
            where table1_id = t1.id
           ) t2
      where seqnum <= 10
     ) t2
     on true left join 
where t1.other = other_value;

Это, вероятно, лучший подход.

...