between
句を使用してクエリを実行すると、終了値が除外されるようです。
例えば:
select * from person where dob between '2011-01-01' and '2011-01-31'
これにより、「2011-01-01」から「2011-01-30」までのdob
のすべての結果が取得されます。 dob
が '2011-01-31'であるレコードをスキップします。誰もこのクエリがこのように動作する理由と、dob
が '2011-01-31'であるレコードを含めるようにクエリを変更する方法を説明できますか? (ユーザーによって選択されているため、終了日に1を追加しません。)
フィールドdob
にはおそらく時間コンポーネントがあります。
切り捨てるには:
select * from person
where CAST(dob AS DATE) between '2011-01-01' and '2011-01-31'
MySQL-manual から:
これは式(min <= expr AND expr <= max)と同等です
問題は、2011-01-31が実際に2011-01-31 00:00:00であることです。それが一日の始まりです。日中のすべてが含まれていません。
select * from person where dob between '2011-01-01 00:00:00' and '2011-01-31 23:59:59'
クエリで参照しているフィールドはDateタイプですか、またはDateTimeタイプですか?
説明する動作の一般的な原因は、実際にDate型を使用する必要があるDateTime型を使用する場合です。つまり、誰かがいつ生まれたのかを本当に知る必要がない限り、Date型を使用します。
最終日が結果に含まれない理由は、クエリで指定されなかった日付の時間部分をクエリが想定しているためです。
つまり、クエリは2011年1月30日から2011年1月31日までの午前0時までと解釈されていますが、データは2011年1月31日のその日の後半に値を持つ場合があります。
提案:DateTime型の場合、フィールドを日付型に変更します。
こんにちは、このクエリは私のために機能します、
select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'
select * from person where DATE(dob) between '2011-01-01' and '2011-01-31'
驚くべきことに、このような変換はMySQLの多くの問題の解決策です。
次のようにクエリを実行できます。
select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'
日付がハードコーディングされている場合、他の人が指摘したように。
一方、日付が別のテーブルにある場合は、次のように日を追加して秒を減算できます(日付が秒/時刻なしで保存されている場合)。
select * from person JOIN some_table ... where dob between some_table.initial_date and (some_table.final_date + INTERVAL 1 DAY - INTERVAL 1 SECOND)
dob
フィールドでのキャストは避けてください(受け入れられた回答のように)。これにより、パフォーマンス上の大きな問題(dob
フィールドでインデックスを使用できないなど)が発生する可能性があります。 DATE(dob)
やCAST(dob AS DATE)
のようなものを作成すると、実行計画がusing index condition
からusing where
に変わる可能性があるため、注意してください。
上限日を日付+ 1日に設定します。したがって、この場合、2011-02-01に設定します。