【问题标题】:PostgreSQL: transpose multiple date columns dynamically to rowsPostgreSQL:将多个日期列动态转置为行
【发布时间】:2020-05-17 10:56:52
【问题描述】:

如果之前有人问过这个问题,我深表歉意。我搜索了 Postgres 手册和许多 SO 答案,但仍然找不到解决方案。我正在努力寻找正确的 SQL (postgres) 命令来转换下表:

| client | starts_on  | ends_on    |
|--------|------------|------------|
| ACME   | 2019-12-01 | 2020-02-28 |

进入所需的输出:

| client | year       | month      |
|--------|------------|------------|
| ACME   | 2019       | 12         |
| ACME   | 2020       | 1          |
| ACME   | 2020       | 2          |

这应该用crosstab 完成吗?如果是这样,我该如何使用date_trunc函数?

SELECT
    *
FROM
    crosstab ('SELECT client, date_trunc(' year ', ends_on), date_trunc(' month ', ends_on)
         FROM example_table') 
AS ct ("Client" text,
        "Year" int,
        "Month" int);

这会引发以下错误:

查询 1 错误:错误:“月”或附近的语法错误 LINE 4: crosstab ('SELECT client, date_trunc('month', ends_on), dat...

非常感谢任何指导!

【问题讨论】:

  • 这只是引用。最简单的解决方案是对查询字符串使用美元引用。

标签: sql postgresql crosstab postgres-crosstab


【解决方案1】:

这不是透视/交叉表问题。您需要为两个日期之间的所有月份生成行。使用generate_series()

select t.client, extract(year from gs.dte), extract(month from gs.dte)
from t cross join lateral
     generate_series(t.starts_on, t.ends_on, interval '1 month') gs(dte);

Here 是一个数据库文件。

【讨论】:

    【解决方案2】:

    虽然最初的问题似乎是语义问题,但对包含引号的字符串进行引用可能对未来的读者有用:


    CREATE TABLE example_table
            ( client text
            , ends_on timestamp
            );
    
    SELECT *
    FROM public.crosstab (
    $qq$
    SELECT client, date_trunc('year', ends_on), date_trunc('month', ends_on)
             FROM example_table
    $qq$
    ) AS ct ("Client" text, "Year" int, "Month" int);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 2012-12-14
      • 2021-02-15
      • 1970-01-01
      相关资源
      最近更新 更多