What's a good way to check if two datetimes are on the same calendar day in TSQL?

前端 未结 10 1435
小鲜肉
小鲜肉 2021-02-12 02:15

Here is the issue I am having: I have a large query that needs to compare datetimes in the where clause to see if two dates are on the same day. My current solution, which suck

相关标签:
10条回答
  • 2021-02-12 02:58

    You're spoilt for choice in terms of options here. If you are using Sybase or SQL Server 2008 you can create variables of type date and assign them your datetime values. The database engine gets rid of the time for you. Here's a quick and dirty test to illustrate (Code is in Sybase dialect):

    declare @date1 date
    declare @date2 date
    set @date1='2008-1-1 10:00'
    set @date2='2008-1-1 22:00'
    if @date1=@date2
        print 'Equal'
    else
        print 'Not equal'
    

    For SQL 2005 and earlier what you can do is convert the date to a varchar in a format that does not have the time component. For instance the following returns 2008.08.22

    select convert(varchar,'2008-08-22 18:11:14.133',102)
    

    The 102 part specifies the formatting (Books online can list for you all the available formats)

    So, what you can do is write a function that takes a datetime and extracts the date element and discards the time. Like so:

    create function MakeDate (@InputDate datetime) returns datetime as
    begin
        return cast(convert(varchar,@InputDate,102) as datetime);
    end
    

    You can then use the function for companions

    Select * from Orders where dbo.MakeDate(OrderDate) = dbo.MakeDate(DeliveryDate)
    
    0 讨论(0)
  • 2021-02-12 03:09

    This is much more concise:

    where 
      datediff(day, date1, date2) = 0
    
    0 讨论(0)
  • 2021-02-12 03:10
    where
    year(date1) = year(date2)
    and month(date1) = month(date2)
    and day(date1) = day(date2)
    
    0 讨论(0)
  • 2021-02-12 03:10

    I would use the dayofyear function of datepart:

    
    Select *
    from mytable
    where datepart(dy,date1) = datepart(dy,date2)
    and
    year(date1) = year(date2) --assuming you want the same year too
    

    See the datepart reference here.

    0 讨论(0)
  • 2021-02-12 03:11

    Eric Z Beard:

    the activity date is meant to indicate the local time zone, but not a specific one

    Okay - back to the drawing board. Try this:

    where t.TheDateINeedToCheck BETWEEN (
        dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, @ActivityDate)
        AND
        dateadd(hh, (tz.Offset + ISNULL(ds.LocalTimeZone, 0)) * -1, (@ActivityDate + 1))
    )
    

    which will translate the @ActivityDate to local time, and compare against that. That's your best chance for using an index, though I'm not sure it'll work - you should try it and check the query plan.

    The next option would be an indexed view, with an indexed, computed TimeINeedToCheck in local time. Then you just go back to:

    where v.TheLocalDateINeedToCheck BETWEEN @ActivityDate AND (@ActivityDate + 1)
    

    which would definitely use the index - though you have a slight overhead on INSERT and UPDATE then.

    0 讨论(0)
  • 2021-02-12 03:11

    Regarding timezones, yet one more reason to store all dates in a single timezone (preferably UTC). Anyway, I think the answers using datediff, datepart and the different built-in date functions are your best bet.

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