在PostgreSQL的范围内获取date列表

我想获取两个date(包括他们)在PostgreSQL数据库中的date列表。 例如,如果我有:

  • 开始date:2012年6月29日
  • 结束date:2012年7月3日

那么结果应该是:

29 june 2012 30 june 2012 1 july 2012 2 july 2012 3 july 2012 

PostgreSQL中这样做的最好方法是什么?

谢谢。

 select CURRENT_DATE + i from generate_series(date '2012-06-29'- CURRENT_DATE, date '2012-07-03' - CURRENT_DATE ) i 

甚至更短:

 select i::date from generate_series('2012-06-29', '2012-07-03', '1 day'::interval) i 

作为timestamp

 select generate_series('2012-06-29', '2012-07-03', '1 day'::interval); generate_series ------------------------ 2012-06-29 00:00:00-03 2012-06-30 00:00:00-03 2012-07-01 00:00:00-03 2012-07-02 00:00:00-03 2012-07-03 00:00:00-03 

或铸造date

 select (generate_series('2012-06-29', '2012-07-03', '1 day'::interval))::date; generate_series ----------------- 2012-06-29 2012-06-30 2012-07-01 2012-07-02 2012-07-03 

这应该做到这一点:

 select date '2012-06-29' + i from generate_series(1, (select date '2012-07-3' - date '2012-06-29')) i 

如果你不想在子查询中重复start_date,事情会变得复杂一些:

 with min_max (start_date, end_date) as ( values (date '2012-06-29', date '2012-07-3') ), date_range as ( select end_date - start_date as duration from min_max ) select start_date + i from min_max cross join generate_series(1, (select duration from date_range)) i; 

(请参阅曼尼克的“不重复”问题的更好的版本)

对于这样的事情,它通常在系统中有一个date表。

就像数字表一样,它们可以比使用dynamic生成date更有用,更快捷,特别是当您扩展到大型数据集时。

从1900年到2100年的这样一个date表将会非常小,所以在存储方面没有太多的问题。

编辑:不知道为什么这是被拒绝,它可能是最好的performance。 再加上它有很多其他的优点。 想要将订单链接到一个宿舍的绩效数字? 它是表格之间的简单链接。 (Order.OrderDate – > Dates.Date – > Dates.Quarter – > PerformanceTotal.Quarter)等处理工作日,如一个月的最后一个工作日,或上个月的第一个星期二。 就像数字表一样,我强烈推荐他们!

 select generate_series('2012-06-29', '2012-07-03', '1 day'::interval)::date; 

如果您已经有要查询的数据库:

 SELECT TO_CHAR(date_column,'DD Mon YYYY') FROM some_table WHERE date_column BETWEEN '29 Jun 2012' AND '3 JUL 2012' GROUP BY date_column ORDER BY date_column 

这将导致:

 "29 Jun 2012" "30 Jun 2012" "01 Jul 2012" "02 Jul 2012" "03 Jul 2012" 

如果date范围应该来自表格expression式,则可以使用以下结构:

 DROP TABLE tbl ; CREATE TABLE tbl (zdate date NOT NULL ); INSERT INTO tbl(zdate) VALUES( '2012-07-01') , ('2012-07-09' ); WITH mima AS ( SELECT MIN(zdate)::timestamp as mi , MAX(zdate)::timestamp as ma FROM tbl ) SELECT generate_series( mima.mi, mima.ma, '1 day':: interval):: date FROM mima ; 

因为generate_series()不带date参数,所以需要强制转换。

这个PLpg / SQL函数可以做到这一点:

 CREATE OR REPLACE FUNCTION getDateList(date1 date, date2 date) RETURNS SETOF date AS $BODY$ DECLARE count integer; lower_limit integer := 0; upper_limit integer := date2 - date1; BEGIN FOR count IN lower_limit..upper_limit LOOP RETURN NEXT date1 + count; END LOOP; RETURN; END; $BODY$ LANGUAGE plpgsql VOLATILE 
Interesting Posts