在postgresql中插入缺少的月份

时间:2013-06-10 18:52:49

标签: sql postgresql date partitioning

我有一个按ID分区的WITH表,并计算用户在特定月份创建的项目数:

|      ID |  COUNT |   MONTH |
------------------------------
|       1 |      1 | 2013-01 |
|       1 |      2 | 2013-05 |
|       2 |      1 | 2013-02 |
|       2 |      2 | 2013-04 |
|       2 |      3 | 2013-06 |
|       3 |      1 | 2013-01 |  

在postgresql中,如何将计数添加到缺少的月份以创建这样的最终查询结果?

|      ID |  COUNT |   MONTH |
------------------------------
|       1 |      1 | 2013-01 |
|       1 |      1 | 2013-02 |
|       1 |      1 | 2013-03 |
|       1 |      2 | 2013-04 |
|       1 |      2 | 2013-05 |
|       1 |      3 | 2013-06 |
|       2 |      1 | 2013-02 |
|       2 |      1 | 2013-03 |
|       2 |      2 | 2013-04 |
|       2 |      2 | 2013-05 |
|       2 |      3 | 2013-06 |
|       3 |      1 | 2013-01 |  
|       3 |      1 | 2013-02 |  
|       3 |      1 | 2013-03 |
|       3 |      1 | 2013-04 |
|       3 |      1 | 2013-05 |
|       3 |      1 | 2013-06 |

2 个答案:

答案 0 :(得分:0)

假设MONTH是某种形式的文本字段:

INSERT INTO myTable (id, "count", month)
SELECT t1.id, t1."count", TO_CHAR(r.d, 'YYYY-MM')
FROM myTable as t1
JOIN (SELECT generate_series((min(month) || '-01')::date, 
                                   date_trunc('month',now())::date, 
                                   '1 month') as d
            FROM myTable) AS r 
  ON (t1.month || '-01')::date < r.d
WHERE NOT EXISTS (
  SELECT 1 FROM myTable as t2
  WHERE t1.id = t2.id 
    AND ( (t1."count" < t2."count" AND (t2.month || '-01')::date <= r.d)
         OR (t1."count" = t2."count" AND (t2.month || '-01')::date = r.d))
);

使用sqlfiddle here

答案 1 :(得分:0)

这可以相当简单。

鉴于此表:

CREATE TABLE tbl(id int, ct int, month text);

INSERT INTO tbl (id, ct, month)
VALUES
    (1, 1, '2013-01'),
    (1, 2, '2013-05'),
    (2, 1, '2013-02'),
    (2, 2, '2013-04'),
    (2, 3, '2013-06'),
    (3, 1, '2013-01');

我将ct替换为函数名count,我不会将其用作标识符 假设ct(count)从不低于1并且从不随着给定id的时间而减少,您可以使用此查询(已更新):

SELECT id.id, max(COALESCE(t.ct, 1)) OVER (PARTITION BY id.id 
                                           ORDER BY m.month) AS ct, m.month
FROM   generate_series(1,3) id
CROSS  JOIN (
   SELECT to_char('2013-1-1'::timestamp
          + interval '1 month' * generate_series(0,5), 'YYYY-MM') AS month
   ) m
LEFT   JOIN tbl t USING (id, month)
ORDER  BY id, month;

现在延长了几个月的任意时间。

->SQLfiddle