1

我有一个 Postgres 表,我试图根据一些日期列进行分析。

我基本上是在尝试计算表中满足此要求的行数,然后按月和年对它们进行分组。而不是我的查询看起来像这样:

SELECT * FROM $TABLE WHERE date1::date <= '2012-05-31' 
                       and date2::date > '2012-05-31';

它应该能够在我的数据中显示可用的月份,这样我就不必在每次添加新数据时手动更改月份,这样我就可以通过一个查询获得所有内容。

在上面的例子中,我希望它将符合条件的行的总和分组到 2012 年和 05 月。同样,如果我的 WHERE 子句看起来像这样:

date1::date <= '2012-06-31' and date2::date > '2012-06-31'

我希望它将这笔款项归入 2012 年和 06 月。

4

3 回答 3

1

这对我来说并不完全清楚:

我希望它对行的总和进行分组

我会这样解释:你想“每月”列出所有符合条件的行:

WITH x AS (
    SELECT date_trunc('month', min(date1)) AS start
          ,date_trunc('month', max(date2)) + interval '1 month' AS stop
    FROM   tbl
   )
SELECT to_char(y.mon, 'YYYY-MM') AS mon, t.*
FROM  (
   SELECT generate_series(x.start, x.stop, '1 month') AS mon
   FROM   x
   ) y
LEFT   JOIN tbl t ON t.date1::date <= y.mon 
                 AND t.date2::date >  y.mon   -- why the explicit cast to date?
ORDER  BY y.mon, t.date1, t.date2;

假设date2 >= date1.

  1. 计算时间段的上下边界并截断为月份(在上边界上加 1 以包括最后一行。

  2. 用于generate_series()创建有问题的月份集

  3. LEFT JOIN表中具有声明标准的行并按月排序。

你也可以GROUP BY在这个阶段计算聚合..

于 2012-08-29T08:01:01.133 回答
0

这是推理。首先,创建所有可能日期的列表。然后获取 date1 到给定日期的累计数。然后得到date2之后的累计数,减去结果。以下查询使用相关子查询(不是我最喜欢的构造,但在这种情况下很方便)来执行此操作:

select thedate,
       (select count(*) from t where date1::date <= d.thedate) -
       (select count(*) from t where date2::date > d.thedate)
from (select distinct thedate
      from ((select date1::date as thedate from t) union all
            (select date2::date as thedate from t)
           ) d
     ) d

这是假设 date2 发生在 date1 之后。我的模型是客户的开始和停止日期。如果不是这种情况,则查询可能不起作用。

于 2012-08-27T16:05:31.417 回答
-1

听起来您可以从DATEPART T-SQL 方法中受益。如果我理解正确,您可以执行以下操作:

SELECT DATEPART(year, date1) Year, DATEPART(month, date1) Month, SUM(value_col)
FROM $Table
-- WHERE CLAUSE ?
GROUP BY DATEPART(year, date1),
  DATEPART(month, date1)
于 2012-08-27T16:03:09.947 回答