T-SQL Between Dates Confusion

后端 未结 5 484
一生所求
一生所求 2020-12-03 18:22

I am working with T-SQL in SQL Server 2000 and I have a table TRANSACTIONS which has a date column TRANDATE defined as DateTime, among many other c

相关标签:
5条回答
  • 2020-12-03 19:01

    '12/01/2010' means '12/01/2010 00:00:00' and '12/31/2010' means '12/31/2010 00:00:00'. This is why datetime values that fall later on the day on 12/31/2010 are excluded from your query results.

    0 讨论(0)
  • 2020-12-03 19:06

    As you have discovered, if you don't specify a time when entering a date, it defaults to midnight in the morning of the date. So 12/31/2010 stops at midnight when that day begins.

    To get all dates for 12/31/2010, you can either specify the time, as you have done, or add one day to the ending date. Without a time, 1/1/2011 ends at the stroke of midnight on 12/31/2010. So, you could do BETWEEN 12/1/2010 AND 1/1/2011. You can use DATEADD to add the day in your SQL if that makes it easier.

    There is some risk in that second approach of adding a day. You will get any records for 1/1/2011 that carry the time of 00:00:00.

    Here's one way to perform the DATEADD:

    DECLARE @FromDate datetime, @ToDate datetime
    // These might be stored procedure input parameters
    SET @FromDate = '12/1/2010'
    SET @ToDate = '12/31/2010'
    
    SET @ToDate = DATEADD(d, 1, @ToDate)
    

    Then you use @ToDate in your WHERE clause in the BETWEEN phrase in the usual way.

    0 讨论(0)
  • 2020-12-03 19:16

    You have kind of answered your own question already. What you have observed is the way SQL Server works.

    If it is confirmation you need, this MSDN document has following to say about it

    When the time part is unspecified, it defaults to 12:00 A.M. Note that a row that contains a time part that is after 12:00 A.M. on 1998-0105 would not be returned by this query because it falls outside the range.

    Edit

    As for your comment, a datetime essentially is a floating point value.

    Following script shows what numbers SQL Server works with.
    40541.9749 (12/31/2010 23:23:59) can't be included when your upper bound is 40541 (12/31/2010)

    DECLARE @ADateTime1 DATETIME
    DECLARE @ADateTime2 DATETIME
    DECLARE @ADateTime1AsFloat FLOAT
    DECLARE @ADateTime2AsFloat FLOAT
    
    SET @ADateTime1 = '12/31/2010'
    SET @ADateTime2 = '12/31/2010 23:23:59'
    
    SET @ADateTime1AsFloat = CAST(@ADateTime1 AS FLOAT)
    SET @ADateTime2AsFloat = CAST(@ADateTime2 AS FLOAT)
    
    SELECT @ADateTime1AsFloat, @ADateTime2AsFloat
    
    0 讨论(0)
  • 2020-12-03 19:19

    A date is a point in time, not a time span.

    '12/31/2010' is a point, too. Namely, it's the midnight of the 31st of December.
    Everything that happened after this point is ignored.
    That's exactly the behaviour you want (even if you haven't realised that yet).

    Do not think that when you choose to omit the time part, it is magically assumed to be "any". It's going to be "all zeroes", that is, the midnight.

    If you want to include the entire day in your query without having to specify 23:59:59 (which, by the way, excludes the last second of the day, between the moment 23:59:59 of the current day and the moment 00:00:00 of the next day), you can do that either by using strict inequalities (>, <) bounded by the first points of time you don't want:

    WHERE TRANDATE >='12/01/2010 00:00:00' and TRANDATE < '01/01/2011'
    

    or by comparing date values casted to DATE:

    WHERE CAST(TRANDATE AS DATE) between '12/01/2010' and '12/31/2010'
    

    (it is okay to put this type of cast in a WHERE clause, it is sargable).

    0 讨论(0)
  • 2020-12-03 19:19

    What would be your expected result if I would do this

    Insert "12/31/2010" into your datetime column?
    

    Exactly: 12-31-2010 00:00:00

    So why would you expect it to be different as argument for a query?

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