Найдите пятницу, к которому конкретная дата «ближе всего» в T-Sql - PullRequest
4 голосов
/ 01 марта 2010

Я ищу элегантный простой способ определить дату пятницы, которая ближе всего к определенной дате. Есть идеи?

Ответы [ 5 ]

2 голосов
/ 01 марта 2010

Хитрость заключается в том, чтобы определить, сколько дней до ближайшей пятницы от предложенной даты. Чтобы помочь, посмотрите на целую неделю и количество дней до ближайшей пятницы:

Воскресенье -2
Понедельник -3
Вторник 3
Среда 2
Четверг 1
Пятница 0
Суббота -1

Теперь вам нужна формула для возврата этих результатов. Поскольку воскресенье и понедельник следуют другим правилам недели, необходимы две формулы.

Во-первых, вот воскресенье и понедельник. Он добавляет 1 к значению дня недели, затем принимает отрицательное значение, чтобы применить к добавлению даты. Например, понедельник по умолчанию имеет значение 2 в качестве значения дня недели. (2 + 1) * -1 = -3. -3 + понедельник = пятница.

Вторник - суббота используют аналогичную арифметику: даты возвращают значения дня недели 3, 4, 5, 6 и 7. Нам нужно добавить значения даты 3,2,1,0, -1 соответственно. Формула, чтобы получить это: 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
2 голосов
/ 01 марта 2010

Возвращает ближайшую пятницу в будущем:

SELECT  DATEADD(day, 6 - (DATEDIFF(day, '01/01/2010', @mydate) - 1) % 7, @mydate)
1 голос
/ 01 марта 2010

Вы должны сдвинуть начало недели (используя DATEFIRST), чтобы вторник стал серединой недели, а затем просто добавьте количество дней, чтобы перейти к ближайшей пятнице.

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
0 голосов
/ 05 ноября 2015

Решение SQL Server как пользовательская функция. Будет округлять не только до ближайшей пятницы, но и до ближайшего любого дня недели (1-7), который вы укажете:

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
0 голосов
/ 01 марта 2010

, если вам нужно найти ближайшую (прошлую или будущую) пятницу, попробуйте это:

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

ВЫВОД:

DateOf
-----------------------
2010-02-26 00:00:00.000

(1 row(s) affected)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...