次の表があります。
+-----------+-----------+------------+----------+
| 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になることです。
SELECT *
FROM mytable
WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE);
日時関数 はドキュメントの関連セクションです。
すべての「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つの列の逆順に注意してください。詳細な説明:
ちょうど同じ質問があり、これが役立つ場合は、このように答えました。
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'
ロケール設定でクエリを機能させるには、 日付のフォーマット を自分で検討してください。
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');
それが機能しない日付を見てください-日が12以下である日付-日付をYYYY-DD-MM形式として解析しているのだろうか?
SELECT *
FROM ecs_table
WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE + interval '1');
日付部分の取得方法を使用する必要があります。
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')
攻撃はありませんが、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番目です。