在多列的单行中显示多行数据

Posted

技术标签:

【中文标题】在多列的单行中显示多行数据【英文标题】: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 ) 是保证每天一排还是会少几天? 【参考方案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

【讨论】:

以上是关于在多列的单行中显示多行数据的主要内容,如果未能解决你的问题,请参考以下文章

Spark:如何将多行转换为具有多列的单行?

将多行加入单行中的多列 Netezza/Postgres

oracle单行多列,拆分成多行

将多行连接成单行并计算 SQL Server 中连接的行数

Oracle-子查询实例

ServiceNow如何在Fufiller页面端实现String的多行与单行转换