13

Postgres 9.1 データベースで、特定の月の一連の週を生成しようとしていますが、いくつかの制約があります。すべての週を月曜日に開始し、別の月に開始または終了するときにカットする必要があります。

例:

2013 年 2 月には、次のようなシリーズを生成したいと考えています。

         start
------------------------
2013-02-01 00:00:00+00
2013-02-04 00:00:00+00
2013-02-11 00:00:00+00
2013-02-18 00:00:00+00
2013-02-25 00:00:00+00

私が今持っているクエリは次のようになります。

SELECT GREATEST(date_trunc('week', dates.d),
                date_trunc('month',dates.d)) as start
FROM generate_series(to_timestamp(1359676800),to_timestamp(1362095999), '1 week') as dates(d)

このクエリは最初の 4 週間を取得しますが、25 日からの 1 週間が欠落しています。最後の週を取得することは可能ですか?

4

2 に答える 2

15
SELECT generate_series(date_trunc('week', date '2013-02-01' + interval '6 days')
                     , date_trunc('week', date '2013-02-01' + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
UNION  SELECT date '2013-02-01'
ORDER  BY 1;

このバリアントは副選択を必要としないGREATESTGROUP BY、必要な行のみを生成します。より簡単に、より速く。UNION1列の方が安いです。

  • その月の最初の月曜日を計算するには、前月の最初の日に 6 日を追加します。date_trunc('week', ...)

  • 月の最終月曜日date_trunc('week', ...)を取得するには、1 か月を加算して 1 日前を減算します。これは便利に 1 つの式 に詰め込むことができます。
    interval'1 month - 1 day'

  • UNION(ではありません UNION ALL) 月曜日として既に含まれていない限り、追加する月の最初の日。

  • date+のinterval結果はであることに注意してtimestampください。ここではこれが最適です。詳細な説明:

オートメーション

CTE で日付系列の開始を指定できます。

WITH t(d) AS (SELECT date '2013-02-01')  -- enter 1st of month once
SELECT generate_series(date_trunc('week', d + interval '6 days')
                     , date_trunc('week', d + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
FROM   t
UNION  SELECT d FROM t
ORDER  BY 1;

または、繰り返し呼び出しを行う際に便利なように、単純な SQL 関数にラップします。

CREATE OR REPLACE FUNCTION f_week_starts_this_month(date)
  RETURNS SETOF date AS
$func$
SELECT generate_series(date_trunc('week', $1 + interval '6 days')
                     , date_trunc('week', $1 + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
UNION
SELECT $1
ORDER  BY 1
$func$  LANGUAGE sql IMMUTABLE;

電話:

SELECT * FROM f_week_starts_this_month('2013-02-01');

月の最初の日の日付を渡しますが、どの日付でも機能します。翌月の初日とすべての月曜日。

于 2013-03-15T17:22:48.677 に答える
7
select
    greatest(date_trunc('week', dates.d), date_trunc('month',dates.d)) as start
from generate_series('2013-02-01'::date, '2013-02-28', '1 day') as dates(d)
group by 1
order by 1
于 2013-03-15T17:11:07.103 に答える