セミオープン(またはハーフオープン、ハーフクローズ、ハーフバウンド)間隔([a,b)
、x
間隔iffに属するa <= x < b
)は、多くの便利なプロパティがあるため、プログラミングではかなり一般的です。
誰もがSQL BETWEEN
が閉じた間隔([a,b]
)を使用する理由を説明する根拠を提供できますか?これは特にです。日付に不便。なぜBETWEEN
こんなふうに振る舞うのでしょうか?
セミオープン(またはハーフオープン、ハーフクローズ、ハーフバウンド)間隔([a,b)
、x
間隔iffに属するa <= x < b
)は、多くの便利なプロパティがあるため、プログラミングではかなり一般的です。
誰もがSQL BETWEEN
が閉じた間隔([a,b]
)を使用する理由を説明する根拠を提供できますか?これは特にです。日付に不便。なぜBETWEEN
こんなふうに振る舞うのでしょうか?
回答:
インクルーシブBETWEEN
は、セミオープンの間隔よりも直感的です(そして、明らかに、SQLデザイナーもそうでした)。たとえば、「1から10までの数字を選んでください」と言うと、ほとんどの人は1から10までの数字を含めます。SQLは、プログラマではない人が簡単なクエリを作成するために使用することがあり、セミオープンセマンティクスはそれらをはるかに混乱させます。
質問:なぜSQLのBETWEENは包括的ですか?
回答:SQL言語の設計者は、開発者がBETWEENの4つのバリアント(closed、semi-open-left、semi-open-right、またはopen )彼らは好むだろう。
推奨事項:SQL標準が修正されるまで/修正されるまで、日付/時刻にBETWEENを使用しないでください。代わりに、BETWEEN範囲の開始境界と終了境界の独立した条件として、日付範囲比較をコーディングする習慣を身に付けます。これは少し冗長ですが、データベースオプティマイザーにとってわかりやすい(したがってバグが少ない)条件を記述し、最適な実行計画を決定し、使用するインデックスを作成できます。
たとえば、クエリが入力日の指定を受け入れ、その日付に該当するすべてのレコードを返す必要がある場合、次のようにコーディングします。
WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1
BETWEENを使用してロジックを記述しようとすると、パフォーマンスの問題やバグのあるコードが危険にさらされます。3つのよくある失敗:
1) WHERE DATE_FIELD BETWEEN :dt AND :dt+1
これはほぼ間違いなくバグです。ユーザーは特定の日付のレコードのみを表示することを期待していますが、ある日は翌日の午前12:00からのレコードを含むレポートで終わります。
2) WHERE TRUNC(DATE_FIELD) = :dt
正しい答えを与えますが、関数をDATE_FIELDに適用すると、ほとんどのインデックス付け/統計情報が役に立たなくなります(ただし、DBAは関数ベースのインデックスを日付フィールドに追加することで助けようとします-依然として工数とディスク容量を燃やし、IUDにオーバーヘッドを追加します)テーブルでの操作)
3) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60
オラクルの第一人者であるTom Kyteは、この優劣(IMO)ソリューションを推奨しています。不完全な結果を与えるクエリでその「1-1 / 24/06/60」を見つけるために1日を過ごすまで、または誤ってTIMESTAMPフィールドでそれを使用するまで、うまく機能します。さらに、それは少し独自のものです。OracleのDATEデータ型(秒まで追跡)と互換性がありますが、異なるデータベース製品の日付/時刻の精度に調整する必要があります。
解決策:ANSI SQL委員会に対し、BETWEEN構文を変更してCLOSED / INCLUSIVEのデフォルトの代替の仕様をサポートすることにより、SQL言語仕様を強化するように要請します。このような何かがトリックを行います:
expr1 BETWEEN expr2 [ INCL [USIVE] | EXCL [USIVE]]およびexpr3 [ INCL [USIVE] | 排他的] ]
表現するのがどれだけ簡単になるかWHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(または単にWHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)を考慮する
たぶんANSI SQL:2015?
exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3
には、between演算子を保持する方法が気に入っているので、範囲付きの述語であり、不等号の述語はそれが半開であることを保証します。
包括的(a <= x <= b
)と排他的(a < x < b
)の両方はほぼ同じように一般的であるため、標準を作成するときはどちらかを選択するだけでした。通常、一般的な英語の「間」は包括的であり、SQLステートメントは英語の文と同様に読むことを意図しているため、包括的が賢明な選択でした。
a <= x < b
ハーフオープンです。
オペレータが呼び出されていない∩[a,b)
、それが呼ばれていますBETWEEN
、それはそれらのことをその意味論のための適切なかなりですので、英語のフレーズ数学的な述語のものより「間にある」「セミオープン区間です」。
BETWEEN
オペレーターが英語のフレーズ「is between」のセマンティクスを使用しないことです。英語で「between」は、物事を分離する時間、空間、または間隔です(つまり、排他的です)。ゴールをキックしようとすると、ボールはポスト間を行き来して得点しなければなりません。あなたがそれらの間を通過することに失敗した投稿をヒットした場合-あなたのためのスコアはありません。