web-dev-qa-db-ja.com

PostgreSQLの2つの日付間の結果を取得する

次の表があります。

+-----------+-----------+------------+----------+
| id        | user_id   | start_date | end_date |
| (integer) | (integer) | (date)     | (date)   |
+-----------+-----------+------------+----------+

フィールドstart_dateおよびend_dateは、YYYY-MM-DDなどの日付値を保持しています。

このテーブルのエントリは、(1, 120, 2012-04-09, 2012-04-13)のようになります。

特定の期間に一致するすべての結果を取得できるクエリを作成する必要があります。

問題は、2012-01-01から2012-04-12に結果を取得したい場合、start_date = "2012-04-09"およびend_date = "2012-04-13"のエントリがあっても結果が0になることです。

30
Psyche
 SELECT *
   FROM mytable
  WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE);

日時関数 はドキュメントの関連セクションです。

51
Marco Mariani

すべての「overlapping」期間、つまり、少なくとも1日共通の期間が必要だと仮定します。

期間をまっすぐなタイムラインで想定し、目の前で移動すると、必要な条件がseeになります。

SELECT *
FROM   tbl
WHERE  start_date <= '2012-04-12'::date
AND    end_date   >= '2012-01-01'::date;

これはOVERLAPSよりも速い場合があります-これは他の良い方法です( @ Marcoが既に提供されています )。

微妙な違いドキュメントごと )に注意してください:

OVERLAPSは、ペアの以前の値を自動的に開始として受け取ります。各期間は、半開間隔start <= time < end、startとendが等しい場合を除き、その場合、その単一の時刻を表します。これは、たとえば、共通のエンドポイントのみを持つ2つの期間が重複しないことを意味します。

大胆な強調鉱山。

性能

大きなテーブルの場合、右側のindexはパフォーマンスに役立ちます(a lot)。

CREATE INDEX tbl_date_inverse_idx ON tbl(start_date, end_date DESC);

追加の選択条件がある場合は、おそらく別の(先頭の)インデックス列を使用します。

2つの列の逆順に注意してください。詳細な説明:

29

ちょうど同じ質問があり、これが役立つ場合は、このように答えました。

select * 
from table
where start_date between '2012-01-01' and '2012-04-13'
or    end_date   between '2012-01-01' and '2012-04-13'
20
Chris

ロケール設定でクエリを機能させるには、 日付のフォーマット を自分で検討してください。

SELECT * 
  FROM testbed 
 WHERE start_date >= to_date('2012-01-01','YYYY-MM-DD')
   AND end_date <= to_date('2012-04-13','YYYY-MM-DD');
1
vyegorov

それが機能しない日付を見てください-日が12以下である日付-日付をYYYY-DD-MM形式として解析しているのだろうか?

0
Edmund
SELECT *
FROM ecs_table
WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE + interval '1');
0
user9251288

日付部分の取得方法を使用する必要があります。

SELECT * FROM testbed WHERE start_date  ::date >= to_date('2012-09-08' ,'YYYY-MM-DD') and date::date <= to_date('2012-10-09' ,'YYYY-MM-DD')
0
boopathiraja

攻撃はありませんが、sqlのパフォーマンスを確認するために、上記のpgsqlのソリューションを実行しました。

私が出会ったトップ3のソリューションアプローチの統計をご紹介します。

1)かかった:平均1.58 MS

2)かかった:平均2.87 MS

3)かかった:平均3.95 MS

今これを試してください:

 SELECT * FROM table WHERE DATE_TRUNC('day', date ) >= Start Date AND DATE_TRUNC('day', date ) <= End Date

現在、このソリューションは、1.61 Avg。

そして、最良の解決策は marco-mariani によって提案された1番目です。

0
rxpande