Sql 如何获取Postgres过去12周的发票数量

Sql 如何获取Postgres过去12周的发票数量,sql,postgresql,asp.net-mvc-3,aggregate-functions,generate-series,Sql,Postgresql,Asp.net Mvc 3,Aggregate Functions,Generate Series,发票数据库包含发票日期: create table dok ( dokumnr serial primary key, invoicedate date not null ); 仪表板需要逗号分隔的列表,其中包含过去12周的发票数量,e.q 4,8,0,6,7,6,0,6,0,4,5,6 列表始终包含12个元素。如果在大约7天的时间间隔内没有发票,则应显示0。 每个元素应包含7天的发票数量 查询应找到当前日期之前的最长日期: select max(invoicedate) as las

发票数据库包含发票日期:

create table dok (
  dokumnr serial primary key,
  invoicedate date not null
);
仪表板需要逗号分隔的列表,其中包含过去12周的发票数量,e.q

4,8,0,6,7,6,0,6,0,4,5,6

列表始终包含12个元素。如果在大约7天的时间间隔内没有发票,则应显示0。 每个元素应包含7天的发票数量

查询应找到当前日期之前的最长日期:

select max(invoicedate) as last_date from dok;
然后可能使用count*和string_agg创建列表

最后12个元素应包含的发票数量

  last_date .. last_date-interval'6days'
11最后一项之前的要素应包含发票天数

  last_date-interval'7days' .. last_date-interval'14days'
等等

如何在Postgres 9.1+中编写此查询? 这是ASP.NET MVC3 C应用程序,如果有帮助的话,查询的某些部分也可以用C代码完成

我以

with list as (

SELECT count(d.invoicedate) as cnt
   FROM  (
      SELECT max(invoicedate) AS last_date
      FROM   dok
      WHERE   invoicedate< current_date
      ) l
   CROSS  JOIN generate_series(0, 11*7, 7) AS g(days)
   LEFT   JOIN dok d ON d.invoicedate>  l.last_date - g.days - 7
                    AND d.invoicedate<= l.last_date - g.days
   GROUP  BY g.days
   ORDER  BY g.days desc
)

SELECT string_agg( cnt::text,',')
from list
交叉连接生成_系列的最新日期,然后左连接到主表

SELECT ARRAY(
   SELECT count(d.invoicedate) AS ct
   FROM  (
      SELECT max(invoicedate) AS last_date
      FROM   dok
      WHERE  invoicedate < current_date  -- "maximum date before current date"
      ) l
   CROSS  JOIN generate_series(0, 11*7, 7) AS g(days)
   LEFT   JOIN dok d ON d.invoicedate >  l.last_date - g.days - 7
                    AND d.invoicedate <= l.last_date - g.days
   GROUP  BY g.days
   ORDER  BY g.days
   );
您的查询已审核: 这是一个实施细节

聚合函数array_agg、json_agg、jsonb_agg、, json_object_agg、jsonb_object_agg、string_agg和xmlagg,如下所示 以及类似的用户定义聚合函数,生成有意义的 不同的结果值取决于输入值的顺序。 默认情况下,此顺序未指定,但可以由控制 在聚合调用中编写ORDERBY子句,如中所示 . 或者,从 排序的子查询通常会工作。例如:

SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;
请注意,如果外部查询级别包含 附加处理,例如联接,因为这可能导致 要在计算聚合之前对子查询的输出进行重新排序

我的。 要保持符合标准,您可以编写:

WITH list AS (
   SELECT g.days, count(d.invoicedate)::text AS cnt
   FROM  (
      SELECT max(invoicedate) AS last_date
      FROM   dok
      WHERE  invoicedate < current_date
      ) l
   CROSS  JOIN generate_series(0, 11*7, 7) AS g(days)
   LEFT   JOIN dok d ON d.invoicedate >  l.last_date - g.days - 7
                    AND d.invoicedate <= l.last_date - g.days
   GROUP  BY 1
   )
SELECT string_agg(cnt, ',' ORDER BY days DESC)
FROM   list;
但这有点慢。此外,CTE在技术上不是必需的,而且比子查询慢一点。
SELECT array_to_stringARRAY SELECT…,','像我建议的那样是最快的,因为对于单个结果,数组构造函数比聚合函数字符串快。

谢谢。我在问题的更新部分以查询结束。这样行吗?它最近一周会回来吗?安德鲁斯:会的。考虑一下我的答案的补遗。
WITH list AS (
   SELECT g.days, count(d.invoicedate)::text AS cnt
   FROM  (
      SELECT max(invoicedate) AS last_date
      FROM   dok
      WHERE  invoicedate < current_date
      ) l
   CROSS  JOIN generate_series(0, 11*7, 7) AS g(days)
   LEFT   JOIN dok d ON d.invoicedate >  l.last_date - g.days - 7
                    AND d.invoicedate <= l.last_date - g.days
   GROUP  BY 1
   )
SELECT string_agg(cnt, ',' ORDER BY days DESC)
FROM   list;