简体   繁体   中英

SQL Server : group by week off by 1 day

Using the syntax

dateadd(week, datediff(week, 0, CURRENT_TIMESTAMP),0)

to group data by week it appears that the last day of the week gets put into the following week.

In a simple example

print dateadd(week, datediff(week, 0, '27 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '28 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '29 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '30 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '31 jan 2012 00:00'),0)

I would expect to return

Jan 23 2012 12:00AM
Jan 23 2012 12:00AM
Jan 23 2012 12:00AM
Jan 30 2012 12:00AM
Jan 30 2012 12:00AM

or

Jan 22 2012 12:00AM
Jan 22 2012 12:00AM
Jan 29 2012 12:00AM
Jan 29 2012 12:00AM
Jan 29 2012 12:00AM

depending on DATEFIRST settings I guess

however it returns

Jan 23 2012 12:00AM
Jan 23 2012 12:00AM
Jan 30 2012 12:00AM
Jan 30 2012 12:00AM
Jan 30 2012 12:00AM

ie the 29 January is in the week of 30th January not 23rd January or 30th January as expected.

I'm clearly missing something but can't think what it might be.

This is correct.

No matter what @@DATEFIRST is, there is always the same number of whole weeks between now and 01 Jan 1900. As @@DATEFIRST changes, it affects both "start" and "end" week.

DATEADD then just adds 7 day periods because it ignores @@DATEFIRST

You can force it by choosing the DATEADD base

Example: 01 Jan 1900 is a Monday.

You want Sunday? Then base to 31 Dec 1899

print dateadd(week, datediff(week, 0, '27 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '28 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '29 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '30 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '31 jan 2012 00:00'),-1)

You want Tuesday? Then base to 02 Jan 1900

print dateadd(week, datediff(week, 0, '27 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '28 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '29 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '30 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '31 jan 2012 00:00'),1)

This should convert the date to the first day of the week for the purposes of grouping

set datefirst 1
select dateadd(day, -1 * (datepart(weekday, getdate()) - 1), getdate())

Note that the set datefirst 1 sets the first day of the week as Monday. You can alter this statement to change the first day of the week to fit to your expectations (see http://msdn.microsoft.com/en-us/library/ms181598.aspx )

DATEDIFF doesn't respect the DATEFIRST setting.

Here's a similar question, with a potential workaround:

Is it possible to set start of week for T-SQL DATEDIFF function?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM