web-dev-qa-db-ja.com

MS SQL Serverは「間」に範囲の境界を含みますか?

例えばすることができます

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

5と10を選択するか、それらは範囲から除外されますか?

222
Lea Verou

BETWEEN演算子は包括的です。

Books Onlineから:

Test_expressionの値がbegin_expressionの値以上かつend_expressionの値以下の場合、BETWEENはTRUEを返します。

DateTimeの警告

注意:DateTimesを使用する場合は注意が必要です。日付のみが指定されている場合、値はその日の深夜0時のものと見なされます。終了日内の欠落時間を避けるため、または翌日のデータのキャプチャを午前0時に複数の範囲で繰り返すことを避けるために、終了日は、終了日の翌日の午前0時の3ミリ秒前にする必要があります。これより小さい値と値は翌日の深夜0時に切り上げられるため、3ミリ秒です。

例えば2016年6月以内にすべての値を取得するには、実行する必要があります。

where myDateTime between '20160601' and DATEADD(millisecond, -3, '20160701')

すなわち.

where myDateTime between '20160601 00:00:00.000' and '20160630 23:59:59.997'

datetime2とdatetimeoffset

日付から3ミリ秒を減算すると、3ミリ秒のウィンドウから行が失われる可能性があります。正しい解決策はまた最も簡単なものです:

where myDateTime >= '20160601' AND myDateTime < '20160701'
248
DJ.

はい、ただし日付の間に使う場合は注意してください。

BETWEEN '20090101' AND '20090131'

本当に午前12時と解釈される、または

BETWEEN '20090101 00:00:00' AND '20090131 00:00:00'

1月31日の日中に起こったことは何でも見逃すことはないでしょう。この場合は、使用する必要があります。

myDate >= '20090101 00:00:00' AND myDate < '20090201 00:00:00'  --CORRECT!

または

BETWEEN '20090101 00:00:00' AND '20090131 23:59:59' --WRONG! (see update!)

UPDATE20090101 23:59:59.997のように遅い日時で、その日の最後の1秒以内にレコードを作成することは完全に可能です。

このため、BETWEEN (firstday) AND (lastday 23:59:59)アプローチはお勧めできません。

代わりにmyDate >= (firstday) AND myDate < (Lastday+1)アプローチを使用してください。

良い この問題に関する記事はこちら

248
BradC

SQL Server 2008の実例です。

元データ:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000
3     2010-05-01 00:00:00.000
4     2010-07-31 00:00:00.000

クエリ:

SELECT
    *
FROM
    tbl
WHERE
    Start BETWEEN '2010-04-01 00:00:00' AND '2010-05-01 00:00:00'

結果:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000

alt text

16
Ryan Rodemoyer

これに当たっても、実際にコードに1日を追加しようとしても対処したくない場合は、DBに任せてください。

myDate >= '20090101 00:00:00' AND myDate < DATEADD(day,1,'20090101 00:00:00')

時間部分を含める場合は、必ず深夜0時を参照してください。それ以外の場合は、単に時間を省略することができます。

myDate >= '20090101' AND myDate < DATEADD(day,1,'20090101')

心配する必要はありません。

13
Shaun

_ (Transact-SQL)

テストする(n)(包含)範囲を指定します。

test_expression [ NOT ] BETWEEN begin_expression AND end_expression

引数

test_expression

テストする式がbegin_expressionとend_expressionで定義された範囲内にあるかどうか。 test_expressionはbegin_expressionとend_expressionの両方と同じデータ型でなければなりません。

NOT

述語の結果が否定されることを指定します。

begin_expression

任意の有効な式です。 begin_expressionは、test_expressionとend_expressionの両方と同じデータ型でなければなりません。

end_expression

任意の有効な式です。 end_expressionは、test_expressionとbegin_expressionの両方と同じデータ型でなければなりません。

AND

Test_expressionがbegin_expressionとend_expressionで示される範囲内にあることを示すプレースホルダーとして機能します。

備考

排他的範囲を指定するには、大なり記号(>)と小なり記号(<)を使用します。 BETWEEN述語またはNOT BETWEEN述語への入力がNULLの場合、結果はUNKNOWNになります。

結果値

Test_expressionの値がbegin_expressionの値以上かつend_expressionの値以下の場合、BETWEENはTRUEを返します。

Test_expressionの値がbegin_expressionの値より小さいか、end_expressionの値より大きい場合、NOT BETWEENはTRUEを返します。

12
Russ Cam

列のデータ型がdatetimeの場合は、datetimeから時間を削除し、日付範囲のみを比較するために次のようにすることができます。

where cast(getdate() as date) between cast(loginTime as date) and cast(logoutTime as date)
3
Kahlil Vanz

それは境界を含みます。

declare @startDate date = cast('15-NOV-2016' as date) 
declare @endDate date = cast('30-NOV-2016' as date)
create table #test (c1 date)
insert into #test values(cast('15-NOV-2016' as date))
insert into #test values(cast('20-NOV-2016' as date))
insert into #test values(cast('30-NOV-2016' as date))
select * from #test where c1 between @startDate and @endDate
drop table #test
RESULT    c1
2016-11-15
2016-11-20
2016-11-30


declare @r1 int  = 10
declare @r2 int  = 15
create table #test1 (c1 int)
insert into #test1 values(10)
insert into #test1 values(15)
insert into #test1 values(11)
select * from #test1 where c1 between @r1 and @r2
drop table #test1
RESULT c1
10
11
15
0
Halim