【问题标题】:Display data from multiple rows in a single row with multiple columns在多列的单行中显示多行数据
【发布时间】:2013-02-19 10:47:54
【问题描述】:

我有一个 PostgreSQL 数据库,其中包含一些带有时间戳的记录。

是否有简单的方法在一段时间内(例如一个月,使用 PRECEDING 和 FOLLOWING 表达式)收集窗口中的数据,然后创建包含该月所有记录的多个列(例如,每月每天 30 列)?

让我们考虑这个简单的案例:一个包含两列 timestampmeasurement 的表。 我想要的是获得 31 列的表:时间戳和measurement1measurement2 ... measurement30,其中measurement_i 是时间戳前 i 天的测量值。

【问题讨论】:

  • 窗口函数在“windows”上运行。在您的情况下,窗口的定义是什么?我想说这是真正的问题要在这里解决。
  • 窗口很简单:WINDOW w AS ( ORDER BY timestamp RANGE BETWEEN '30 days'::interval PRECEDING AND '0 days'::interval FOLLOWING )
  • 是保证每天一排还是会少几天?

标签: sql postgresql crosstab window-functions


【解决方案1】:

如果你想要 multiple rows 在结果中,我会使用 crosstab() 函数。

但根据您的描述,您需要一个单行。我会用 window functions lead() or lag() 解决这个问题。
主要技巧是在应用 WHERE 子句并将结果缩小到单行之前使用子查询或 CTE 生成所有列。我会在这里使用CTE

鉴于下表(您应该提供):

CREATE TABLE tbl(
  tbl_id serial PRIMARY KEY
 ,ts timestamp NOT NULL
 ,value int
);

保证每天一排

查询可能如下所示:

WITH x AS (
   SELECT tbl_id, ts, value
         ,lag(value, 1) OVER w AS value_day_before_1
         ,lag(value, 2) OVER w AS value_day_before_2
   --    ...
         ,lead(value, 1) OVER w AS value_day_after_1
         ,lead(value, 2) OVER w AS value_day_after_2
   --    ...
   FROM   tbl
   WINDOW w AS (ORDER BY ts) 
   )
SELECT *
FROM   x
WHERE  ts = '2013-02-14 0:0'::timestamp

每天最多一行,但可以缺少天数:

时间戳也可以是一天中的任何时间。

生成包含generate_series()LEFT JOIN 的日期列表:

WITH x AS (
   SELECT tbl_id, ts, value
         ,lag(value, 1) OVER w AS value_day_before_1
         ,lag(value, 2) OVER w AS value_day_before_2
   --    ...
         ,lead(value, 1) OVER w AS value_day_after_1
         ,lead(value, 2) OVER w AS value_day_after_2
   --    ...
   FROM   (
       SELECT generate_series ('2013-02-01'::date
                              ,'2013-02-28'::date
                              ,interval '1d') AS day
       ) d
   LEFT JOIN tbl t ON date_trunc('day', t.ts) = d.day
   WINDOW w AS (ORDER BY day) 
   )
SELECT *
FROM   x
WHERE  ts = '2013-02-14 0:0'::timestamp;

->sqlfiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-11
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 2014-04-09
    相关资源
    最近更新 更多