Does MS SQL Server's “between” include the range boundaries?

前端 未结 8 2134
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-27 10:53

For instance can

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

select 5 and 10 or they are excluded from the range?

相关标签:
8条回答
  • 2020-11-27 11:23

    Yes, but be careful when using between for dates.

    BETWEEN '20090101' AND '20090131'
    

    is really interpreted as 12am, or

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

    so will miss anything that occurred during the day of Jan 31st. In this case, you will have to use:

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

    or

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

    UPDATE: It is entirely possible to have records created within that last second of the day, with a datetime as late as 20090101 23:59:59.997!!

    For this reason, the BETWEEN (firstday) AND (lastday 23:59:59) approach is not recommended.

    Use the myDate >= (firstday) AND myDate < (Lastday+1) approach instead.

    Good article on this issue here.

    0 讨论(0)
  • 2020-11-27 11:24

    The BETWEEN operator is inclusive.

    From Books Online:

    BETWEEN returns TRUE if the value of test_expression is greater than or equal to the value of begin_expression and less than or equal to the value of end_expression.

    DateTime Caveat

    NB: With DateTimes you have to be careful; if only a date is given the value is taken as of midnight on that day; to avoid missing times within your end date, or repeating the capture of the following day's data at midnight in multiple ranges, your end date should be 3 milliseconds before midnight on of day following your to date. 3 milliseconds because any less than this and the value will be rounded up to midnight the next day.

    e.g. to get all values within June 2016 you'd need to run:

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

    i.e.

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

    datetime2 and datetimeoffset

    Subtracting 3 ms from a date will leave you vulnerable to missing rows from the 3 ms window. The correct solution is also the simplest one:

    where myDateTime >= '20160601' AND myDateTime < '20160701'
    
    0 讨论(0)
  • 2020-11-27 11:25

    If the column data type is datetime then you can do this following to eliminate time from datetime and compare between date range only.

    where cast(getdate() as date) between cast(loginTime as date) and cast(logoutTime as date)
    
    0 讨论(0)
  • 2020-11-27 11:28

    if you hit this, and don't really want to try and handle adding a day in code, then let the DB do it..

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

    If you do include the time portion: make sure it references midnight. Otherwise you can simply omit the time:

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

    and not worry about it.

    0 讨论(0)
  • 2020-11-27 11:33

    It does includes boundaries.

    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 讨论(0)
  • 2020-11-27 11:39

    I've always used this:

    WHERE myDate BETWEEN startDate AND (endDate+1)

    0 讨论(0)
提交回复
热议问题