PostgreSQL:将多个日期列动态转置为行
PostgreSQL: transpose multiple date columns dynamically to rows
如果之前有人问过这个问题,我深表歉意。我已经搜索了 Postgres 手册和许多 SO 答案,但仍然找不到解决方案。我正在努力寻找正确的 SQL (postgres) 命令来转换以下 table:
| 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);
这将引发以下错误:
Query 1 ERROR: ERROR: syntax error at or near "month"
LINE 4: crosstab ('SELECT client, date_trunc('month', ends_on), dat...
任何指导将不胜感激!
这不是 pivoting/cross 选项卡问题。您需要为两个日期之间的所有月份生成行。使用 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 是一个 db<>fidle。
尽管原始问题似乎是一个语义问题,引用包含引号的字符串 可能对未来的读者有用:
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);
如果之前有人问过这个问题,我深表歉意。我已经搜索了 Postgres 手册和许多 SO 答案,但仍然找不到解决方案。我正在努力寻找正确的 SQL (postgres) 命令来转换以下 table:
| 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);
这将引发以下错误:
Query 1 ERROR: ERROR: syntax error at or near "month" LINE 4: crosstab ('SELECT client, date_trunc('month', ends_on), dat...
任何指导将不胜感激!
这不是 pivoting/cross 选项卡问题。您需要为两个日期之间的所有月份生成行。使用 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 是一个 db<>fidle。
尽管原始问题似乎是一个语义问题,引用包含引号的字符串 可能对未来的读者有用:
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);