要生成一系列日期,这是最佳方法:
SELECT t.day::date
FROM generate_series(timestamp '2004-03-07'
, timestamp '2004-08-16'
, interval '1 day') AS t(day);
等效的,不太明确的简短语法:
SELECT day::date
FROM generate_series(timestamp '2004-03-07', '2004-08-16', '1 day') day;
或使用SELECT
列表中的返回设置功能:
SELECT generate_series(timestamp '2004-03-07', '2004-08-16', '1 day')::date AS day;
该AS
关键字需要在最后的变体,Postgres的会曲解列别名day
除外。而且我不建议在Postgres 10之前使用该变体-至少不要在同一SELECT
列表中具有多个set-returning函数:
(顺便说一句,最后一个变体通常最快的幅度很小。)
为什么timestamp [without time zone]
呢
有许多重载的变体generate_series()
。目前(Postgres 11):
SELECT oid::regprocedure AS function_signature
, prorettype::regtype AS return_type
FROM pg_proc
where proname = 'generate_series';
function_signature | return_type
:------------------------------------------------- ------------------------------- | :--------------------------
generate_series(integer,integer,integer)| 整数
generate_series(integer,integer)| 整数
generate_series(bigint,bigint,bigint)| 比金特
generate_series(bigint,bigint)| 比金特
generate_series(数字,数字,数字)| 数字
generate_series(数字,数字)| 数字
generate_series(没有时区的时间戳,没有时区的时间戳,间隔)| 没有时区的时间戳
generate_series(带时区的时间戳,带时区的时间戳,间隔)| 带时区的时间戳
(numeric
在Postgres 9.5中添加了变体。)相关的是粗体末尾并返回timestamp
/的最后两个timestamptz
。
有没有变异服用或返回date
。需要显式转换才能返回date
。带timestamp
参数的调用可以直接解析为最佳变体,而无需遵循函数类型解析规则,也无需为输入进行额外的转换。
timestamp '2004-03-07'
顺便说一句,完全有效。省略的时间部分默认为00:00
ISO格式。
由于函数类型解析,我们仍然可以通过date
。但这需要Postgres进行更多工作。有一个隐含的投从date
到timestamp
以及从一个date
到timestamptz
。会模棱两可,但在“日期/时间类型”中timestamptz
是“首选”。因此,在第4d步确定比赛。:
遍历所有候选项,并将那些接受首选类型(输入数据类型的类别)的候选项保留在需要进行类型转换的大多数位置。如果没有候选人接受首选类型,则保留所有候选人。如果只剩下一名候选人,请使用它;否则继续下一步。
除了在函数类型解析中的额外工作之外,这还增加了额外的转换timestamptz
-不仅增加了成本,而且还可能引入DST问题,在极少数情况下会导致意外结果。(顺便说一句,DST是一个愚蠢的概念,对此压力还不够。)
我在小提琴中添加了演示,显示了更昂贵的查询计划:
db <>在这里拨弄
有关: