Nice programing

PostgreSQL의 범위에서 날짜 목록 가져 오기

nicepro 2021. 1. 5. 21:10
반응형

PostgreSQL의 범위에서 날짜 목록 가져 오기


PostgreSQL 데이터베이스 에서 두 날짜 (날짜 포함) 사이의 날짜 목록을 얻고 싶습니다 . 예를 들어 다음과 같은 경우 :

  • 시작일 : 2012 년 6 월 29 일
  • 종료일 : 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;

( "반복 없음"문제의 훨씬 더 나은 버전은 maniek의 답변을 참조하십시오)


이와 같은 경우 일반적으로 시스템에 날짜 테이블이 있으면 편리합니다.

숫자 테이블과 마찬가지로, 특히 대규모 데이터 세트로 확장 할 때 즉석에서 날짜를 생성하는 것보다 매우 유용하고 사용하기 더 빠를 수 있습니다.

Such a date table from 1900 to 2100 will be very small, so there isn't much over head in storage.

Edit: Dunno why this is getting voted down, it will probably be the best for performance. Plus it has so many other advantages. Want to link orders to a an quarters performance numbers? Its a simple link between the tables. (Order.OrderDate -> Dates.Date -> Dates.Quarter -> PerformanceTotal.Quarter) etc. Its the same for dealing with working days, like the last working day of a month, or the first Tuesday of the previous month. Like a numbers table, I'd strongly recommend them!


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

If you already have database that you want to query:

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

This will result in:

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

If the date range should come from a table expression, you could use the following construct:

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
        ;

The casts are needed because generate_series() does not take date arguments.


This PLpg/SQL function would do the trick:

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

ReferenceURL : https://stackoverflow.com/questions/11391085/getting-date-list-in-a-range-in-postgresql

반응형