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

How to show all dates from a certain date range in horizontal row?

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

|  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() 的帮助下我可以做到 "vertically",但是如何在一行中得到结果?

使用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

  • Generating time series between two dates in PostgreSQL

为什么 LEFT JOIN .. ON true

尽管在这种特殊情况下 LEFT JOIN 不是必需的(可以是 CROSS JOIN),因为 ARRAY 构造函数总是 returns 一行。

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<>fiddle here

但考虑升级到当前版本。

crosstab()?

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

  • Dynamic alternative to pivot with CASE and GROUP BY
  • Dynamically generate columns for crosstab in PostgreSQL
  • PostgreSQL Crosstab Query