如何在水平行中显示某个日期范围内的所有日期?

时间:2018-11-01 00:44:16

标签: sql time-series row postgresql-9.1 generate-series

我在PostgreSQL中有一个名为t1的数据库表,例如:

|  Name  |  | StartDate |  | EndDate   |
----------------------------------------
| Oct-18 |  | 2018-10-01|  | 2018-10-05|

我想要日期范围的结果,例如:

| Oct-18 | |2018-10-01| |2018-10-02| |2018-10-03| |2018-10-04| |2018-10-05|

generate_series()的帮助下,我可以“垂直”地进行操作,但是如何在单行中获得结果?

1 个答案:

答案 0 :(得分:2)

使用generate_series()。但是SQL不允许动态数量的结果列。因此,您必须将结果包装在字符串,数组或文档类型中以使其起作用。 在LATERAL子查询中使用ARRAY构造函数的示例-在Postgres 10或更高版本中:

SELECT t1.name, d.date_arr::date[]
FROM   t1
LEFT   JOIN LATERAL (
   SELECT ARRAY(SELECT generate_series(t1.startdate::timestamp
                                     , t1.enddate::timestamp
                                     , interval '1 day'))
   ) d(date_arr) ON true;

为什么(最好是)Postgres 10或更高版本?

为什么要强制转换为timestamp

为什么要LEFT JOIN .. ON true

Postgres 9.1

LATERAL需要Postgres 9.3或更高版本。您可以用相关的子查询代替:

SELECT name
     , ARRAY(SELECT generate_series(startdate::timestamp
                                  , enddate::timestamp
                                  , interval '1 day')::date)
FROM   t1;

即使与pg 8.4兼容:

db <>提琴here

但是请考虑升级到当前版本。

crosstab()

crosstab()也无法克服SQL的静态特性。准备好的行类型的解决方法很有限...