Это можно сделать с помощью рекурсивного запроса, который сгенерирует интервал месяцев, для которого нам нужно найти первый и последний 10 счетов.
WITH RECURSIVE all_months AS (
SELECT date_trunc('month','2018-01-01'::TIMESTAMP) as c_date, date_trunc('month', '2018-05-11'::TIMESTAMP) as end_date, to_char('2018-01-01'::timestamp, 'YYYY-MM') as current_month
UNION
SELECT c_date + interval '1 month' as c_date,
end_date,
to_char(c_date + INTERVAL '1 month', 'YYYY-MM') as current_month
FROM all_months
WHERE c_date + INTERVAL '1 month' <= end_date
),
invocies_with_month as (
SELECT *, to_char(invoice_date::TIMESTAMP, 'YYYY-MM') invoice_month FROM invoice
)
SELECT current_month, array_agg(first_10.id), 'FIRST 10' as type FROM all_months
JOIN LATERAL (
SELECT * FROM invocies_with_month
WHERE all_months.current_month = invoice_month AND invoice_date >= '2018-01-01' AND invoice_date <= '2018-05-11'
ORDER BY invoice_date ASC limit 10
) first_10 ON TRUE
GROUP BY current_month
UNION
SELECT current_month, array_agg(last_10.id), 'LAST 10' as type FROM all_months
JOIN LATERAL (
SELECT * FROM invocies_with_month
WHERE all_months.current_month = invoice_month AND invoice_date >= '2018-01-01' AND invoice_date <= '2018-05-11'
ORDER BY invoice_date DESC limit 10
) last_10 ON TRUE
GROUP BY current_month;
В приведенном выше коде '2018-01-01 'и' 2018-05-11 'представляют даты между тем, когда мы хотим найти счета.На основе этих дат мы генерируем месяцы (2018-01, 2018-02, 2018-03, 2018-04, 2018-05), для которых нам нужно найти счета.Мы храним эти данные в all_months .
После того, как мы получим месяцы, мы выполняем боковое объединение, чтобы присоединяться к счетам за каждый месяц.Нам нужно 2 боковых соединения, чтобы получить первые и последние 10 счетов.Наконец, результат представляется в виде:
current_month - месяц
array_agg - идентификаторы всех выбранных счетов за этот месяц
type - тип выбранных счетов-фактур («первые 10» или «последние 10»).
Таким образом, в текущей реализации у вас будет 2 строки для каждого месяца (если естьпо крайней мере 1 счет за этот месяц).Вы можете легко объединить это в один ряд, если вам нужно.