Postgresqlの日時フィールドの日付を比較するにはどうすればよいですか?


188

postgresql(Windowsではバージョン9.2.4)の日付を比較すると、奇妙なシナリオに直面していました。テーブルに 'timestamp without timezone'タイプのupdate_dateという列があります。クライアントは、日付(例:2013-05-03)または日付(例:2013-05-03 12:20:00)のみでこのフィールドを検索できます。この列には、現在すべての行のタイムスタンプとしての値があり、日付部分(2013-05-03)は同じですが、時間部分が異なります。

この列を比較すると、異なる結果が得られます。次のように:

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date < '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-04' -> results found

select * from table where update_date >= '2013-05-03' -> results found

私の質問は、最初のクエリで結果を取得できるようにする方法です。つまり、3番目のクエリは機能しているが、最初のクエリは機能していないのはなぜですか。

誰かがこれを手伝ってくれる?前もって感謝します。

回答:


278

@Nicolaiはキャストについて正しく、どのデータに対しても条件がfalseになる理由です。入力文字列での日付操作を避けたいので、最初の形式を選ぶと思いますよね?あなたは恐れる必要はありません:

SELECT *
FROM table
WHERE update_date >= '2013-05-03'::date
AND update_date < ('2013-05-03'::date + '1 day'::interval);

この構文('2013-05-03'::dateおよび'1 day'::interval)はPostgreSQL固有ですか?
Frozen Flame

5
@FrozenFlameはい、そうです。標準構文はCAST('2013-05-03' AS DATE) + CAST('1 day' AS INTERVAL)(IIRC)です。存在や行動にメーリングリストへDATEINTERVAL
ちょうど誰か

@FrozenFlameは正しいです。文字列を日付型にキャストしないと、答えは機能しません。1つのキャストがまだありません。::DATEwhere句の最初の部分に追加する必要があります
StillLearningToCode

ではないだろうWHERE update_date::date = '2013-05-03' としても、多分少し読みやすく動作しますか?
MikeF

@MikeF OPは言っupdate_datetimestamp without timezone。その列のインデックスを想定しました。述語はそのインデックスを使用しません。
ちょうど誰か

46

比較する場合、update_date >= '2013-05-03'postgresは値を同じ型にキャストして値を比較します。したがって、「2013-05-03」は「2013-05-03 00:00:00」にキャストされました。

したがって、update_date = '2013-05-03 14:45:00'の場合、式は次のようになります。

'2013-05-03 14:45:00' >= '2013-05-03 00:00:00' AND '2013-05-03 14:45:00' <= '2013-05-03 00:00:00'

これは常に false

この問題を解決するには、update_dateをdate次のようにキャストします。

select * from table where update_date::date >= '2013-05-03' AND update_date::date <= '2013-05-03' -> Will return result

1
update_dateテーブル内のすべてをキャストすることと、クエリパラメーターの単一の値をキャストすることは、非常に非効率的であり、サーバーがその列のインデックスを活用できないようにします。私はこれを-1に誘惑します。
2013年

3
はい、私は各値のキャストが非効率的であり、このソリューションに-1を与える可能性があることに同意します。しかし、問題の理由を説明し、問題を実証する例を示しました。これで、user2866264は彼のクエリが予期された行を返さない理由を理解し、彼のユニークなケースに最適なソリューションを正確に決定します。
Nicolai

@Nicolai:回答ありがとうございます。それはあなたの答えに従うことによって機能します。説明もありがとうございます。
user2866264 2013年

1
@Nicolai – Postgresが日付リテラルを真夜中のストロークに拡張することについて言ったことを考えると、目標が単一の日付(5月3日)でマークされたレコードを見つけることである場合、このコードは正しく、より効率的ですSELECT * FROM my_table WHERE update_date >= '2013-05-03' AND update_date < '2013-05-04'; (5月4日の使用に注意してください) 3番目ではなく、以下の記号ではなくLESS-THAN SIGNを使用します。)
Basil Bourque 2013年


2

日付変換を使用して日付と比較します:これを試してください:

select * from table 
where TO_DATE(to_char(timespanColumn,'YYYY-MM-DD'),'YYYY-MM-DD') = to_timestamp('2018-03-26', 'YYYY-MM-DD')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.