我想在 PostgreSQL数据库中获取两个日期(包括它们)之间的天数列表。例如,如果我有:
然后结果应该是:
29 june 2012
30 june 2012
1 july 2012
2 july 2012
3 july 2012
在PostgreSQL中执行此操作的最佳方式是什么?
感谢。
答案 0 :(得分:80)
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
答案 1 :(得分:34)
作为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
答案 2 :(得分:7)
这应该这样做:
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;
(请参阅maniek的答案,了解更好的“无重复”问题)
答案 3 :(得分:5)
对于这样的事情,在系统中有一个日期表通常很方便。
就像数字表一样,它们比使用动态生成日期更有用,更快捷,尤其是当您扩展到大型数据集时。
这样的日期表从1900年到2100年将非常小,所以存储空间不大。
编辑:不知道为什么这会被拒绝,这可能是最好的表现。此外,它还有许多其他优点。想要将订单链接到季度绩效数字?它是表之间的简单链接。 (Order.OrderDate - > Dates.Date - > Dates.Quarter - > PerformanceTotal.Quarter)等。它与处理工作日相同,例如一个月的最后一个工作日,或上一个星期二月。像数字表一样,我强烈推荐它们!
答案 4 :(得分:4)
select generate_series('2012-06-29', '2012-07-03', '1 day'::interval)::date;
答案 5 :(得分:0)
如果您已经拥有要查询的数据库:
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"
答案 6 :(得分:0)
这个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
答案 7 :(得分:0)
如果日期范围应来自表格表达式,则可以使用以下结构:
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()不接受日期参数。