web-dev-qa-db-ja.com

タイムスタンプ列に昼/夜インジケーターを追加するにはどうすればよいですか?

行が昼間または夜間に作成されたかどうかを示すために使用するtimestamp列があります。私のコードは次のとおりですが、何らかの理由で「DAY」しか結果として得られません。値を正しくフォーマットしていませんか?

select record_id, rec_date,
       case when date_part('hour', rec_date) between 20 and 07 then 'Night'
            else 'Day' end as Indicator
from records;      

rec_date列は、2019-11-20 21:34:02.000000などの値が表示されるタイムスタンプです。'Night'インジケーターが表示されます。

2
ColRow
_SELECT record_id, rec_date
     , CASE WHEN rec_date::time <  '08:00' THEN 'Night'
            WHEN rec_date::time >= '20:00' THEN 'Night'
            ELSE 'Day' END AS indicator
FROM  records;
_

どうして?

date-format ではなく date-math の問題です。あなたは正確かつ効率的に数学をしたいです。 「日」と「夜」の形式は問題ではありません。

McNetsはすでにBETWEENと_BETWEEN SYMMETRIC_を比較しています。しかし、最終的には_BETWEEN SYMMETRIC 20 AND 07_は依然として醜く、遅く、正しくありません

  1. SYMMETRICは、事前にどちらが大きいかわからないパラメーター化された境界でのみ意味があります。そうでない場合、_20_および_07_は定数です。

  2. _BETWEEN SYMMETRIC 20 AND 07_は最終的に_BETWEEN 07 AND 20_として評価されるため、単純にケースに適用すると、昼と夜が逆になります(より高価です)。

  3. はい、「日」と「夜」を切り替えることで簡単に修正できます。しかし今、時間20:**と07:**は「日」というタグが付けられます。 BETWEENは、SYMMETRICの有無にかかわらず、上限および下限を含みます。それが ほとんどの場合、タイムスタンプで使用するツールが間違っている理由です 。この特定のケースでは、date_part()は、両方の境界をある程度含めることで、組み込みの問題に対抗します。どちらの方法でも、元の意図に合わせるには、次のようにする必要があります。

    _CASE WHEN date_part('hour', ts) BETWEEN '08' AND '19'  -- adjusted
         THEN 'Day' ELSE 'Night' END AS indicator
    _
  4. date_part('hour', rec_date) BETWEEN SYMMETRIC 20 AND 07を使用したクエリは、expensiveの約2倍です。無意味なSYMMETRICによる大きな部分は、キャストよりも関数のコストが高いため小さな部分です。

  5. 推奨される式は、どの境界が含まれるかを明確にするため、不正なBETWEENよりも誤解される可能性がはるかに低くなります。

アサイド

datetimestampとは異なる基本データ型であるため、タイムスタンプ列を「record_date」とは呼びません。混乱の可能性が高まります。

実際のデータタイプがtimestamptzの場合(または、場合によっては、いずれにせよ)、whereを定義する必要があります。昼か夜か"。見る:

10

docs BETWEENは次のように変換されます。

xとyの間

に相当

a> = x AND a <= y

つまり、xはyよりも小さくなければなりません。

また、ドキュメントにはBETWEEN SYMMETRICがあり、質問に役立ちます。

BETWEEN SYMMETRICはBETWEENに似ていますが、ANDの左側の引数が右側の引数以下である必要はありません。そうでない場合、これらの2つの引数は自動的に入れ替えられるため、空でない範囲が常に暗示されます。

create table test (id int);
insert into test values (1),(2),(3),(4),(5),(6);

select id from test where id between symmetric 4 and 2;
 | id | 
 | -:| 
 | 2 | 
 | 3 | 
 | 4 | 

db <> fiddle ここ

4
McNets