Does BETWEEN with dates actually work in SQL SERVER 2008

后端 未结 8 901
旧时难觅i
旧时难觅i 2021-01-20 00:36

According to cdonner, in his answer here and on his blog.

He claims that BETWEEN with date yields inconsistent results

From his blog:

<
相关标签:
8条回答
  • 2021-01-20 00:56

    I have to use something like this:

    Declare @BeginDate SmallDateTime
    Declare @EndDate SmallDateTime
    Set @BeginDate = '2007-08-01'
    Set @EndDate = '2007-08-31'
    
    Select *
    From dbo.table1 a
    Where a.session_date Between @BeginDate + ' 00:00:00' And @EndDate + ' 23:59:59'
    Order By a.session_date asc
    

    To get correct BETWEEN datetime's

    0 讨论(0)
  • 2021-01-20 00:59

    SQL server stores datetime values as a number. For instance, 0 is 1900-01-01 00:00:00.000

    The example you give in your question is subject to rounding problems, similar to how the floating-point value 1.0 is stored as 0.99999...

    To accurately compare dates, you would cast the value to a datetime type and then do your comparison.

    SELECT
    CASE 
        WHEN cast('1/1/08' as datetime) 
            BETWEEN cast('1/1/08' as datetime) AND cast('2/1/08' as datetime) 
        THEN 'in' ELSE 'out' 
    END AS s1,
    CASE 
        WHEN cast('1/1/08' as datetime) 
            BETWEEN cast('12/31/07' as datetime) AND cast('1/1/08' as datetime) 
        THEN 'in' ELSE 'out' 
    END AS s2
    

    Which will result in your expected output: s1==in, s2==in

    0 讨论(0)
  • 2021-01-20 01:00

    In Oracle:

    select
        case when '1/1/08' between '1/1/08' and '2/1/08'
            then 'in' else 'out' end as s1,
        case when '1/1/08' between '12/31/07' and '1/1/08'
            then 'in' else 'out' end as s2
    FROM dual
    
    in out
    

    You are comparing strings here, not dates.

    There is nothing BETWEEN 12/31/07 and 1/1/08, as 2 goes after / in ASCII

    0 讨论(0)
  • 2021-01-20 01:00

    Just never ever use BETWEEN with datetime values. In MySQL I can do

    created >= CURDATE() - INTERVAL 1 DAY AND created < CURDATE()
    

    to limit created to (the whole of) yesterday.

    With BETWEEN '2011-05-02' AND '2011-05-02 23:59:59' I would be gambling on one-second resolution, and would miss a created of '2011-05-02 23:59:59.001'.

    0 讨论(0)
  • 2021-01-20 01:07

    Because he's totally wrong - it's comparing strings

    if you cast them to a datetime or replace them with date variables it works:

    select
        case when CAST('JAN 01 2008' as smalldatetime)
            between CAST('JAN 01 2008' as smalldatetime)
            and CAST('FEB 01 2008' as smalldatetime)
            then 'in' else 'out' end as s1,
        case when CAST('JAN 01 2008' as smalldatetime)
            between CAST('DEC 31 2007' as smalldatetime)
            and CAST('JAN 01 2008' as smalldatetime)
            then 'in' else 'out' end as s2
    
    0 讨论(0)
  • 2021-01-20 01:08

    The code on the blog was nonsense, and I owe Mark for pointing that out to me. The issue exists. It has nothing to do with BETWEEN, but with rounding (which can cause BETWEEN to fail in certain circumstances). While SQL Server does round, .Net does not, and I ran into issues with multiple inserts in a very short timeframe where I assumed that I had distinct datetime values, but due to rounding they became the same in the database. The post was corrected a long time ago, and the code examples still work on SQL Server 2008.

    If you run this query, you will see what I was referring to:

    select convert(varchar(32), convert(datetime,
                                '9/1/08 00:00:00.005'), 121);
    
    0 讨论(0)
提交回复
热议问题