我正在使用PostgreSQL,以获取特定日期之间每个月的前10张和后10张发票。我在横向连接中有意外的输出。首先,限制不起作用,并且每个array_agg
聚合都返回数百行,而不是限制为10行。其次,即使一个聚合被排序ASC
且其他DESC
。
我如何只检索每个月组的前10张发票和最后10张发票?
SELECT first.invoice_month,
array_agg(first.id) first_ten,
array_agg(last.id) last_ten
FROM public.invoice i
JOIN LATERAL (
SELECT id, to_char(invoice_date, 'Mon-yy') AS invoice_month
FROM public.invoice
WHERE id = i.id
ORDER BY invoice_date, id ASC
LIMIT 10
) first ON i.id = first.id
JOIN LATERAL (
SELECT id, to_char(invoice_date, 'Mon-yy') AS invoice_month
FROM public.invoice
WHERE id = i.id
ORDER BY invoice_date, id DESC
LIMIT 10
) last on i.id = last.id
WHERE i.invoice_date BETWEEN date '2017-10-01' AND date '2018-09-30'
GROUP BY first.invoice_month, last.invoice_month;
答案 0 :(得分:0)
event generate
工作正常。是您的查询已损坏。 LIMIT
只是此处错误工具的100%;它甚至没有做任何接近您需要的事情。通过将最多10行与最多另外10行连接起来,您最多可以返回100行。也没有理由仅合并过滤器就自行加入。
请考虑使用窗口查询。特别是,我们具有JOIN
函数,该函数可以根据组对结果集中的每一行进行编号:
dense_rank
不要被长度吓倒。这个查询实际上非常简单。它只需要几个子查询。
这是其逻辑上的作用:
这是专为您要完成的工作而设计的工具集。如果确实需要,可以略微调整此方法以使它们进入同一行,但是必须先进行汇总 ,然后再将结果结合在一起,然后在当月加入;您不能加入然后聚合。
答案 1 :(得分:0)
这可以通过递归查询来完成,该查询将生成一个月间隔,以了解我们需要查找前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个发票。 最后,结果表示为:
当前月-月
array_agg -该月所有选定发票的ID
类型-所选发票的类型(“前10个”或“后10个”)。
因此,在当前实施中,您每个月将有2行(如果该月至少有1张发票)。您可以根据需要轻松地将其加入一行。