PostgreSQLデータベースの2つの日付(それらを含む)の間の日のリストを取得したいと思います。たとえば、私が持っていた場合:
結果は次のようになります。
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の回答を参照してください)
このようなことを行うには、システムに日付テーブルを作成すると一般的に便利です。
数値テーブルと同じように、特に大規模なデータセットにスケールアップする場合、その場で日付を生成するよりも非常に便利で使いやすくなります。
1900年から2100年までのこのような日付テーブルは非常に小さいため、ストレージのオーバーヘッドはあまりありません。
編集:ダンノ、なぜこれが投票されているのか、それはおそらくパフォーマンスにとって最高でしょう。さらに、他にも多くの利点があります。注文を4分の1のパフォーマンス値にリンクしたいですか?テーブル間のシンプルなリンク。 (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"
この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
日付範囲がテーブル式に由来する場合、次の構成を使用できます。
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()は日付引数を受け取らないため、キャストが必要です。