11

I need to group some records based on a date but it is a date and time field and I need to ignore the time part of is and just group by the date part - here is my SQL as it stands:

SELECT   
    AutoShipItems.CustomerID,AutoShipItems.NextOrderDate,
    Customer.FirstName,Customer.LastName, Customer.EmailAddress
FROM        
    AutoShipItems 
        INNER JOIN    Customer ON 
            AutoShipItems.CustomerID =Customer.CustomerID
WHERE     
    (AutoShipItems.NextOrderDate <= GETDATE())
GROUP BY 
    AutoShipItems.CustomerID, AutoShipItems.NextOrderDate, 
    Customer.FirstName, Customer.LastName, 
    Customer.EmailAddress
ORDER BY 
    AutoShipItems.NextOrderDate
casperOne
  • 73,706
  • 19
  • 184
  • 253
Slee
  • 27,498
  • 52
  • 145
  • 243
  • 1
    Possible duplicate of [How to return the date part only from a SQL Server datetime datatype](http://stackoverflow.com/questions/113045/how-to-return-the-date-part-only-from-a-sql-server-datetime-datatype) – Kenny Evitt Oct 28 '16 at 19:38

7 Answers7

23

You can group by this:

cast(floor(cast(AutoShipItems.NextOrderDate as float)) as datetime)

I put this into a scalar user-defined function to make it easier:

create function [dbo].[xfn_TrimTimeFromDateTime]
(
    @date as datetime
)
returns datetime with schemabinding as
begin
    --- Convert to a float, and get the integer that represents it.
    --- And then convert back to datetime.
    return cast(floor(cast(@date as float)) as datetime)
end

Which you would then call like this:

GROUP BY
    AutoShipItems.CustomerID, 
    dbo.xfn_TrimTimeFromDateTime(AutoShipItems.NextOrderDate), 
    Customer.FirstName, Customer.LastName, Customer.EmailAddress

Note that you might have to change the values in the SELECT clause, since you are grouping by something different now.

casperOne
  • 73,706
  • 19
  • 184
  • 253
17
cast (x as date)

or

year(x)
month(x)
day(x)
abatishchev
  • 98,240
  • 88
  • 296
  • 433
mson
  • 7,762
  • 6
  • 40
  • 70
3

You can use type date with convert or cast.

convert(date, @x)

or

cast(@x as date)
Serj-Tm
  • 16,581
  • 4
  • 54
  • 61
2

What about this:

select convert(datetime, convert(varchar(10), getdate(), 112))
Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
1

If it is all just about grouping, you can convert the datetime expression to int as well.

Simple CAST(datetime AS int) actually rounds the datetime to the nearest date rather than drops the time part. Thence,

CAST(datetime - 0.5 AS int)

Another way:

CAST(CAST(datetime AS float) AS int)

(Unlike datetimes, floats are truncated when cast to int.)

I prefer the former as it is shorter. Not sure which is better in terms of performance, though. Still, the issue may probably only arise on really big arrays of data.

0

See this link for three different versions of a date-only function. Here's the one I ended up using:

CREATE FUNCTION [dbo].[fn_GetDateOnly]  ( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN

    RETURN CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)

END
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • But, why use 111 (japanese) instead of 112 (iso) ? – Frederik Gheysels Feb 12 '09 at 19:17
  • Because ISO format 112 doesn't have punctuation, it's possible for the conversion back to datetime to guess the format wrong. I wish there was a format for yyyy-mm-dd with no time; that would be my preference. – Mark Ransom Feb 12 '09 at 19:32
  • Pls beware that CONVERT(VARCHAR method of removing Time is several times slower than CAST(FLOOR(CAST or DATEADD(DATEDIFF methods See also: http://stackoverflow.com/questions/133081/most-efficient-way-in-ms-sql-to-get-date-from-datetime (which I have tested similarly too) – Kristen Feb 19 '09 at 21:05
  • Actually, just tried SELECT CAST(CONVERT(VARCHAR(10), GetDate(), 111) AS DATETIME) here, and it gives error with my server configuration – Kristen Feb 19 '09 at 21:06
0

You can also just use the plain old SQL convert function. The last argument lets you provide pre-deifined date formats, some of which remove the time. Here is the revised query.

SELECT    AutoShipItems.CustomerID, convert(nvarchar(10), AutoShipItems.NextOrderDate, 110) as NextOrderDate ,Customer.FirstName,Customer.LastName, 
                     Customer.EmailAddress
FROM        AutoShipItems INNER JOIN
                     Customer ON AutoShipItems.CustomerID =Customer.CustomerID
WHERE     (AutoShipItems.NextOrderDate <= GETDATE())
GROUP BY AutoShipItems.CustomerID, convert(nvarchar(10), AutoShipItems.NextOrderDate, 110) , Customer.FirstName, Customer.LastName, 
                     Customer.EmailAddress
ORDER BY AutoShipItems.NextOrderDate
James
  • 12,636
  • 12
  • 67
  • 104