将日志表转换为另一个表,其值分布在每个月

时间:2015-01-15 16:39:45

标签: sql postgresql logging timestamp

我有一个包含值和时间戳的行的表。只要值发生更改,就会插入一行,时间戳指示更改发生的时间。例如,像这样:

 id  | value |         timestamp          
-----+-------+----------------------------
   1 |   736 | 2014-03-18 16:38:22.20548
   2 |   531 | 2014-06-18 16:38:22.664324
   3 |    24 | 2014-07-18 16:38:22.980137
   4 |   530 | 2014-09-22 10:01:36.13856
   5 |   529 | 2014-09-23 10:01:27.202026

我需要Postgresql中的一个查询,它会为一年中的每个月生成一行表。每行都有一个时间戳(每月的第一天)和一个值。该值是在给定月份开始之前插入的第一个表的最后一个值。如果第一个表中没有匹配的行,则该值应为0。像这样:

 id  | value |         timestamp          
-----+-------+----------------------------
   1 |     0 | 2014-01-01 00:00:00.000000
   2 |     0 | 2014-02-01 00:00:00.000000
   3 |     0 | 2014-03-01 00:00:00.000000
   4 |   736 | 2014-04-01 00:00:00.000000
   5 |   736 | 2014-05-01 00:00:00.000000
   6 |   736 | 2014-06-01 00:00:00.000000
   7 |   531 | 2014-07-01 00:00:00.000000
   8 |    24 | 2014-08-01 00:00:00.000000
   9 |    24 | 2014-09-01 00:00:00.000000
  10 |   529 | 2014-10-01 00:00:00.000000
  11 |   529 | 2014-11-01 00:00:00.000000
  12 |   529 | 2014-12-01 00:00:00.000000

我尝试了一段时间,但我没有设法得到完整的结果。我想我需要生成这样的月份列表。

SELECT 
  * 
FROM 
  generate_series('2014-01-01 00:00'::timestamp, now(), '1 month') AS months

然后做一些这样的事情来获得一个月前的最后一次出现:

SELECT 
  * 
FROM first_table
WHERE timestamp < --current_month_selection--
ORDER BY timestamp desc 
LIMIT 1;

我想我需要一个OUTER JOIN和一个CASE条件...... 不幸的是,我没有把它放在一起。有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:1)

实际上,我认为我自己解决了这个问题,这非常简单:

SELECT 
  month,
  COALESCE((SELECT value 
  FROM first_table
  WHERE timestamp < month
  ORDER BY timestamp DESC
  LIMIT 1),0)
FROM 
  generate_series('2014-01-01 00:00'::timestamp, now(), '1 month') AS month