18

PostgreSQL 8.4.11 を使用していますが、奇妙なエラーが見つかりました。クエリを実行すると:

SELECT "documents_document"."given_on" 
FROM "documents_document" 
WHERE (EXTRACT('month' FROM "documents_document"."given_on") = 1
       AND "documents_document"."given_on" 
       BETWEEN '1-01-01 00:00:00' and '1-12-31 23:59:59.999999') 
ORDER BY "documents_document"."created_on" DESC

結果が得られます:

  given_on  
------------
 2002-01-16
 2011-01-25
 2012-01-12
 2012-01-12
 2012-01-12
 2012-01-20
 2012-01-19
 2012-01-13
 2012-01-31
 2012-01-16
 2012-01-31
 2012-01-12
 ...

なんで?

間隔 1-01-01 ... 1-12-31 の日付を期待します。

4

3 に答える 3

34

あなたは期待1-01-01 ... 1-12-31していました...しかし、PostgreSQLはあなたがそれを意味することをどのように知っているのでしょうか?

入力文字列リテラルは、現在のセッションの設定に従って解釈されます (無視されpostgressql.confない限り、既定では一般的な設定になります)。特にdatestyle:

DateStyle( string)

日付と時刻の値の表示形式と、あいまいな日付入力値を解釈するためのルールを設定します。歴史的な理由から、この変数には 2 つの独立したコンポーネントが含まれています。出力形式の指定 ( ISOPostgresSQL、またはGerman) と、年/月/日の順序の入力/出力の指定 ( DMYMDY、またはYMD) です。これらは個別に、またはまとめて設定できます。キーワード Euroandは;Europeanの同義語です。DMYキーワードUSNonEuro、およびNonEuropeanは の同義語ですMDY。詳細については、セクション 8.5を参照してください。組み込みのデフォルトは ですがISO, MDY、initdb は、選択した動作に対応する設定で構成ファイルを初期化します。lc_timeロケール。

(出力形式は主に によって決定されlc_timeます。)

あなたの場合、切断されたタイムスタンプ リテラル1-12-31 23:59:59は明らかに次のように解釈されます。

D-MM-YY h24:mi:ss

あなたが望んでいた間:

Y-MM-DD h24:mi:ss

3つのオプション

  1. datestyleあなたと同じ方法でリテラルを解釈するように設定します。たぶんISO, YMD

  2. to_timestamp()他の設定に関係なく、明確に定義された方法で文字列リテラルを解釈するために使用します。ずっといい。

     SELECT to_timestamp('1-12-31 23:59:59', 'Y-MM-DD h24:mi:ss');
    
  3. できれば、すべての日時リテラルにISO 8601 形式( ) を使用してください。YYYY-MM-DDこれは明確で、どの設定にも依存しません

     SELECT '2001-12-31 23:59:59'::timestamp;
    

クエリの書き換え

あなたのクエリはそもそも間違っています。範囲クエリを別の方法で処理します。お気に入り:

SELECT d.given_on 
FROM   documents_document d
WHERE  EXTRACT('month' FROM d.given_on) = 1
AND    d.given_on >= '2001-01-01 0:0'
AND    d.given_on <  '2002-01-01 0:0'
ORDER  BY d.created_on DESC;

または、さらに簡単に:

SELECT d.given_on 
FROM   documents_document d
WHERE  d.given_on >= '2001-01-01 0:0'
AND    d.given_on <  '2001-02-01 0:0'
ORDER  BY d.created_on DESC;

PostgreSQL 9.2 以降の範囲型が興味深いかもしれません。

于 2012-09-14T14:44:48.010 に答える
2

SELECT '1-12-31 23:59:59.999999'::timestamp;を返します2031-01-12 23:59:59.999999。どうやら Postgres は、世紀のない年を日付の最初の要素とは見なしません。

于 2012-09-14T13:48:49.187 に答える
1

必要な形式を指定しなかったため、ネイティブ形式が返されます。おそらく、誰もがあなたと同じように時間を表していると思っていませんか? 可能なフォーマットを見てみましょう。http://www.postgresql.org/docs/8.2/static/functions-formatting.html

于 2012-09-14T13:52:40.653 に答える