在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