我有一个包含name
、location
、start_date
和end_date
的表。我希望将这些包含日期范围的行转换为离散日期行,同时保持相应的行信息不变。
例:
Name1, Location1, 2015-4-01, 2015-4-04
成为:
Name1, Location1, 2015-4-01
Name1, Location1, 2015-4-02
Name1, Location1, 2015-4-03
Name1, Location1, 2015-4-04
我想我需要使用 PostgreSQL 函数将其创建为新表。
创建一个包含三个必填列的新表:
CREATE TABLE new_tbl (
nam varchar,
loc varchar,
dt date);
由于您希望新表中的记录范围为start_date
-end_date
,并具有日期间隔(包括日期),因此最简单的解决方案是从日期生成一组:
generate_series(start_date::timestamp, end_date::timestamp, '1 day')
您可以简单地在新表上粘贴INSERT
语句:
INSERT INTO new_tbl
SELECT nam, loc, generate_series(start_date::timestamp, end_date::timestamp, '1 day')::date
FROM old_tbl;
由于generate_series
函数使用timestamp
参数,因此需要显式强制转换date
s,然后将生成的timestamp
强制转换回date
s 以匹配列定义。
在现代 Postgres (9.3+) 中,最好在LATERAL
连接FROM
列表中使用集合返回函数:
假设start_date
和end_date
定义NOT NULL
:
CREATE TABLE AS
SELECT name, location, day::date
FROM tbl, generate_series(start_date, end_date, interval '1 day') day;
LATERAL
在这里是隐含的。
关于LATERAL
子查询的手册。
一些相关的答案(有很多):
- 在 Postgres 中从表中的开始日期和结束日期开始Generate_series
- 在PostgreSQL中计算2个日期之间的工作时间
关于LATERAL
(回复评论):
- PostgreSQL中的LATERAL 和子查询有什么区别?
- 如何在PostgreSQL中强制转换要设置的实体
- PostgreSQL unnest() 与元素编号