41

次の表があります。

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

フィールドstart_dateend_dateは のような日付値を保持していますYYYY-MM-DD

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

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

2012-01-01問題は、 toから結果をフェッチしたい場合、 and2012-04-12のエントリがあるにもかかわらず、結果が 0 になることです。start_date = "2012-04-09"end_date = "2012-04-13"

4

9 に答える 9

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

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

于 2012-04-16T09:13:49.143 に答える
37

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

直線的な時間軸で期間を想像し、目の前で動かしてみると、必要な条件が見えてきます。

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

これは、私にとってはより高速な場合がありますOVERLAPS-これは、それを行うための他の良い方法です( @Marcoが既に提供しているため)。

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

OVERLAPSペアの前の値が開始点として自動的に使用されます。各期間はstart <= time < end、開始と終了が等しい場合を除き、ハーフオープン インターバルを表すと見なされます。これは、たとえば、終点のみが共通する 2 つの期間が重複しないことを意味します。

大胆強調鉱山。

パフォーマンス

大きなテーブルの場合、適切なインデックスはパフォーマンスに役立ちます (かなり)。

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

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

2 つの列の順序が逆になっていることに注意してください。詳細な説明:

于 2012-04-16T13:05:56.173 に答える
23

同じ質問があり、このように答えました。

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'
于 2013-04-27T13:46:02.877 に答える
3

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

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');
于 2012-04-16T08:27:46.317 に答える
0

それが機能しない日付(日が12以下の日付)を見ると、日付をYYYY-DD-MM形式として解析しているのではないかと思います。

于 2012-04-16T08:17:51.717 に答える
0

日付部分のフェッチ方法を使用する必要があります。

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')
于 2012-10-09T07:01:34.263 に答える
0

問題はありませんが、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 平均。

そして、最良の解決策は、マルコ・マリアーニによって提案された最初のものです

于 2014-09-12T06:54:56.983 に答える