行が昼間または夜間に作成されたかどうかを示すために使用する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'
インジケーターが表示されます。
_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
_は依然として醜く、遅く、正しくありません。
SYMMETRIC
は、事前にどちらが大きいかわからないパラメーター化された境界でのみ意味があります。そうでない場合、_20
_および_07
_は定数です。
_BETWEEN SYMMETRIC 20 AND 07
_は最終的に_BETWEEN 07 AND 20
_として評価されるため、単純にケースに適用すると、昼と夜が逆になります(より高価です)。
はい、「日」と「夜」を切り替えることで簡単に修正できます。しかし今、時間20:**と07:**は「日」というタグが付けられます。 BETWEEN
は、SYMMETRIC
の有無にかかわらず、上限および下限を含みます。それが ほとんどの場合、タイムスタンプで使用するツールが間違っている理由です 。この特定のケースでは、date_part()
は、両方の境界をある程度含めることで、組み込みの問題に対抗します。どちらの方法でも、元の意図に合わせるには、次のようにする必要があります。
_CASE WHEN date_part('hour', ts) BETWEEN '08' AND '19' -- adjusted
THEN 'Day' ELSE 'Night' END AS indicator
_
式date_part('hour', rec_date) BETWEEN SYMMETRIC 20 AND 07
を使用したクエリは、expensiveの約2倍です。無意味なSYMMETRIC
による大きな部分は、キャストよりも関数のコストが高いため小さな部分です。
推奨される式は、どの境界が含まれるかを明確にするため、不正なBETWEEN
よりも誤解される可能性がはるかに低くなります。
date
はtimestamp
とは異なる基本データ型であるため、タイムスタンプ列を「record_date」とは呼びません。混乱の可能性が高まります。
実際のデータタイプがtimestamptz
の場合(または、場合によっては、いずれにせよ)、whereを定義する必要があります。昼か夜か"。見る:
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 ここ