简体   繁体   English

PostgreSQL:将多个日期列动态转置为行

[英]PostgreSQL: transpose multiple date columns dynamically to rows

My apologies if this has been asked before.如果之前有人问过这个问题,我深表歉意。 I've searched the Postgres manual and many SO answers and still can't find a solution.我已经搜索了 Postgres 手册和许多 SO 答案,但仍然找不到解决方案。 I'm struggling to find the right SQL (postgres) command to convert the following table:我正在努力寻找正确的 SQL (postgres) 命令来转换下表:

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

into the desired output:进入所需的 output:

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

Should this be done with crosstab ?这应该用crosstab来完成吗? If so, how can I use the date_trunc function?如果是这样,我该如何使用date_trunc function?

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);

This throws the following error:这会引发以下错误:

Query 1 ERROR: ERROR: syntax error at or near "month" LINE 4: crosstab ('SELECT client, date_trunc('month', ends_on), dat...查询 1 错误:错误:“月”处或附近的语法错误第 4 行:交叉表('SELECT client,date_trunc('month',ends_on),dat ...

Any guidance would be very much appreciated!任何指导将不胜感激!

This is not a pivoting/cross tab problem.这不是旋转/交叉表问题。 You need to generate rows for all the months between the two dates.您需要为两个日期之间的所有月份生成行。 Use generate_series() :使用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 is a db<>fidle. 是一个 db<>fidle。

Though the original question appears to be a semantic problem, the quoting of strings containing quotes might be useful for future readers:虽然最初的问题似乎是一个语义问题,但包含引号的字符串的引用可能对未来的读者有用:


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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM