0

starts_onフィールドとフィールドを持つテーブルから選択する必要がありends_onます。
これらのオブジェクトをフィルタリングして取得するには、開始日と終了日を渡す必要があります。

現時点では機能しており、次のものを使用しています。

SELECT * FROM ***
WHERE ((starts_on >= START_DATE AND starts_on <= END_DATE) OR
       (ends_on >= START_DATE AND ends_on <= END_DATE) OR
       (starts_on <= END_DATE AND ends_on >= END_DATE))
ORDER BY starts_on, id

少し面倒に見えますが、単純化する簡単な方法がわかりません。何か案が?
Postgres 9.1 を dbms として使用しています。

編集:

 starts_on   | timestamp without time zone | 
 ends_on     | timestamp without time zone | 

例: 1 つのエントリに starts_on = '2012/02/02' と end_on '2012/02/05' がある場合、次の動作が必要です。

  • 開始日 2012/01/01 と終了日 2012/03/01 でフィルターすると、商品を返品したい
  • 開始日 2012/02/04 と終了日 2012/03/01 でフィルターすると、商品を返品したい
  • 開始日 2012/02/05 と終了日 2012/03/01 でフィルターすると、商品を返品したい
  • 開始日 2012/02/04 と終了日 2012/02/04 でフィルターすると、商品を返品したい
  • 開始日 2012/02/06 と終了日 2012/03/01 でフィルターをかけた場合、アイテムが返品されないようにしたい
  • 開始日 2012/01/01 と終了日 2012/02/01 でフィルターすると、アイテムが返されないようにしたい
4

1 に答える 1

2

クエリ

starts_onと の間の期間が と の経過期間とends_on重なるすべての行が必要でSTART_DATEありEND_DATE、「終了」が常に「開始」よりも遅く、関連するすべての列がtimestamp(timeまたはではなくdate) タイプである場合、この単純なクエリは次のようになります。仕事:

SELECT *
FROM   tbl
WHERE  starts_on <= END_DATE
AND    ends_on   >= START_DATE
ORDER  BY starts_on, id;

後で明らかになるように、質問に適合します。

索引

このクエリに最適なインデックスは、次のような複数列のインデックスです。

CREATE INDEX tbl_range_idx ON tbl (starts_on, ends_on DESC)

DESC / ASCインデックスは両方向でほぼ同じように検索できるため、ほとんど同じように機能します。

どうすればわかりますか?

インデックスは最初の条件で検索され、条件を満たすstarts_on <= END_DATE行が先頭にあります。
そこから、Postgres は に従って十分に遅く終了するすべての行を取得できますends_on >= START_DATE。適格な行が最初に来ます。最適なインデックス。

しかし、私の言葉だけを鵜呑みにしないでください - でパフォーマンスをテストしてEXPLAIN ANALYZEください。数回実行して、キャッシュ効果を除外します。

OVERLAPS同じ目的の演算子もあります。ロジックを単純化しますが、それ以外の点で優れているわけではありません。

また、PostgreSQL 9.2 には新しいrangeがあり、独自の演算子があります。ただし、9.1 用ではありません。

于 2012-12-03T01:31:43.850 に答える