我有这样的查询,它很好地生成了两个给定日期之间的一系列日期:
select date '2004-03-07' + j - i as AllDate from generate_series(0, extract(doy from date '2004-03-07')::int - 1) as i, generate_series(0, extract(doy from date '2004-08-16')::int - 1) as j
它在2004-03-07和之间生成162个日期2004-08-16,这正是我想要的。此代码的问题在于,当两个日期来自不同年份时(例如,当我尝试使用2007-02-01和时),它将无法给出正确的答案2008-04-01。
有更好的解决方案吗?
要生成一系列日期,这是最佳方法:
SELECT t.day::date FROM generate_series(timestamp '2004-03-07' , timestamp '2004-08-16' , interval '1 day') AS t(day);
date_trunc()不需要其他。强制转换为date(day::date)会隐式地执行此操作。
但是,也没有必要将日期文字转换date为输入参数。互惠生,timestamp是最好的选择。性能上的优势很小,但是没有理由不采用它。而你不无谓地涉及DST(夏令时间)的规则加上从转换date到timestamp with time zone和背部。见下文。
等效的,不太明确的简短语法:
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函数:
SELECT子句中的多个返回集合的函数的预期行为是什么? (顺便说一句,最后一个变体通常最快的幅度很小。)
为什么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) | integer generate_series(integer,integer) | integer generate_series(bigint,bigint,bigint) | bigint generate_series(bigint,bigint) | bigint generate_series(numeric,numeric,numeric) | numeric generate_series(numeric,numeric) | numeric generate_series(timestamp without time zone,timestamp without time zone,interval) | timestamp without time zone generate_series(timestamp with time zone,timestamp with time zone,interval) | timestamp with time zone (
有没有变异服用或返回date。需要显式的强制转换才能返回date。带timestamp参数的调用可以直接解析为最佳变体,而无需遵循函数类型解析规则,也无需为输入进行额外的转换。
timestamp ‘2004-03-07’顺便说一句,完全有效。省略的时间部分默认为00:00ISO格式。
由于函数类型解析,我们仍然可以通过date。但这需要Postgres进行更多工作。有一个隐含的投从date到timestamp以及从一个date到timestamptz。会模棱两可,但在“日期/时间类型”中timestamptz是“首选”。因此,比赛是在第4d步决定的。:
遍历所有候选项,并将那些接受首选类型(输入数据类型的类别)的候选项保留在需要进行类型转换的大多数位置。如果没有任何候选人接受首选类型,请保留所有候选人。如果仅剩下一名候选人,请使用它;否则,请使用它。否则继续下一步。
除了在函数类型解析方面的额外工作之外,这还增加了额外的转换timestamptz-这不仅增加了成本,而且还可能引入DST问题,在极少数情况下会导致意外结果。(顺便说一句,DST是一个愚蠢的概念,对此压力还不够。)