I'm looking for an elegant simple way to determine the date of the Friday that is closest to a particular date. Any ideas?
这将返回将来最接近的星期五:
SELECT DATEADD(day, 6 - (DATEDIFF(day, '01/01/2010', @mydate) - 1) % 7, @mydate)
The trick is to determine how many days away the closest Friday is from the offered date. To help, look at an entire week and the number of days away from the closest Friday:
Sunday -2
Monday -3
Tuesday 3
Wednesday 2
Thursday 1
Friday 0
Saturday -1
Now you need a formula to return these results. Because Sunday and Monday follow a different pattern from the other days of the week, two formulas are needed.
First, here is the one for Sunday and Monday. It adds 1 to the day of the week value then takes the negative to apply to the date add. For example, Monday has a default of 2 as the day of the week value. (2 + 1) * -1 = -3. -3 + Monday = Friday.
Tuesday - Saturday use similar arithmetic: The dates return the day of week values 3, 4, 5, 6, & 7. We need date add values of 3,2,1,0,-1 respectively. The formula to get this is DW * -1 + 6.
DECLARE @Date AS datetime
SET @Date = '3/1/2010'
SELECT
CASE
WHEN DATEPART(dw, @Date) <= 2
THEN DATEADD(d, -1 * (DATEPART(dw, @Date) + 1), @Date)
ELSE DATEADD(d, DATEPART(dw, @Date) * -1 + 6, @Date)
END AS NearestFriday
You have to slide the beginning of the week (using DATEFIRST
) so that you get Tuesday becomes the middle of the week and then you just add the number of days to go to the closest Friday,.
SET NOCOUNT ON
SET DATEFIRST 3
Declare @DateValue DateTime
SET @DateValue = '1/1/2010'
While @DateValue < '2/1/2011'
BEGIN
PRINT DateAdd (Day, 3 - DatePart (dw, @DateValue), @DateValue)
SET @DateValue = @DateValue + 1
END
if you need to find the closest (past or future) Friday, try this:
DECLARE @StartDate datetime
,@EndDate datetime
,@BeforeDate datetime
SET @StartDate='2010-3-1'---<<<given date, Monday, closest should be '2010-2-26'
SET @EndDate=@StartDate+8
SET @BeforeDate=@StartDate-8
;with AllDates AS
(
SELECT @StartDate AS DateOf, 1 as TypeOf,DATENAME(weekday,@StartDate) AS WeekDayOf, ABS(DATEDIFF(day,@StartDate,@StartDate)) AS DifferenceOf
UNION ALL
SELECT DateOf+1 AS DateOf,2 AS TypeOf,DATENAME(weekday,DateOf+1 ) AS WeekDayOf, ABS(DATEDIFF(day,@StartDate,DateOf+1)) AS DifferenceOf
FROM AllDates
WHERE DateOf<@EndDate-1 AND TypeOf IN (1,2)
UNION ALL
SELECT DateOf-1 AS DateOf,3 AS TypeOf,DATENAME(weekday,DateOf-1 ) AS WeekDayOf, ABS(DATEDIFF(day,@StartDate,DateOf-1)) AS DifferenceOf
FROM AllDates
WHERE DateOf>@BeforeDate-1 AND TypeOf IN (1,3)
)
SELECT TOP 1 DateOf
FROM AllDates
WHERE WeekDayOf='Friday'
ORDER BY DifferenceOf
OUTPUT:
DateOf
-----------------------
2010-02-26 00:00:00.000
(1 row(s) affected)
SQL Server solution as a user-defined function. Will round not just to the nearest Friday, but to the nearest of any weekday (1-7) you specify:
CREATE FUNCTION RoundToNearestWeekday (
--Give this function a date, and the number of the weekday you want to round to the nearest of
@DateInput date, --Date you want to round
@ToWeekdayNumber tinyint --1 = round to nearest Sunday, 2 = round to nearest Monday, etc.
)
RETURNS date
AS
BEGIN
DECLARE @Offset tinyint, @LowNumber smallint, @HighNumber smallint, @NewDate date
SET @Offset = (@ToWeekdayNumber + 3)%7
SET @LowNumber = @Offset-3
SET @HighNumber = @Offset+4
SET @NewDate = dateadd(day,CASE WHEN datepart(weekday,@DateInput) <= @Offset THEN @LowNumber ELSE @HighNumber END - datepart(weekday,@DateInput),@DateInput)
RETURN @NewDate
END
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.