web-dev-qa-db-ja.com

日付範囲間のPostgresqlクエリ

日付が特定の月と年にある場合に結果を返すように私のpostgresql dbに問い合わせようとしています。言い換えれば、私は月 - 年のすべての値が欲しいのです。

これまで私ができた唯一の方法は次のとおりです。

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'

これの問題は私がテーブルを問い合わせる前に最初の日付と最後の日付を計算しなければならないということです。もっと簡単な方法はありますか?

ありがとう

93
John

>= start AND < endを使用すると、日付(および時刻)を使って多くのことが簡単になります。

例えば:

SELECT
  user_id
FROM
  user_logs
WHERE
      login_date >= '2014-02-01'
  AND login_date <  '2014-03-01'

この場合でも、必要な月の開始日を計算する必要がありますが、それはさまざまな方法で簡単に行えます。

終了日も簡略化されています。ちょうど1ヶ月追加するだけです。 28日、30日、31日などに煩わされることはありません。


この構造には、索引の使用を維持できるという利点もあります。


多くの人が次のような形式を提案するかもしれませんが、彼らはしませんインデックスを使用します。

WHERE
      DATEPART('year',  login_date) = 2014
  AND DATEPART('month', login_date) = 2

これには、テーブル内のすべての行の条件を計算すること(スキャン)と、一致する行の範囲を見つけるためにインデックスを使用しないこと(範囲シーク)が含まれます。

151
MatBailie

PostgreSQL 9.2以降 範囲タイプ がサポートされています。次のように書くことができます:

SELECT user_id
FROM user_logs
WHERE '[2014-02-01, 2014-03-01]'::daterange @> login_date

これは、文字列比較よりも効率的でなければなりません

万が一誰かがここに着陸した場合…8.1以降、あなたは単に使うことができます:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'

ドキュメントから:

BETWEEN SYMMETRICは、ANDの左側の引数が右側の引数以下である必要がないことを除いて、BETWEENと同じです。そうでない場合は、これら2つの引数は自動的に交換されるため、常に空でない範囲が暗黙的に暗黙指定されます。

5
HayrolR