For a pair of dates (date1, date2) = (Fri 2021-01-01, Wed 2020-01-01)
I need to extract the day of week from date1 (Friday in this case) then find the nearest Friday (or whatever) for date2.
The result for the above pair would be Fri 2020-01-03
(2 days after that Wednesday) and not Fri 2019-12-27
(5 days before that Wednesday).
There are examples that find previous/next day-of-week, use a hard-coded day of week or use SET DATEFIRST
statement; all of which I must avoid. Here is some test data — pair of dates and expected result:
x
CREATE TABLE #tests (
date1 DATE,
date2 DATE,
result DATE
);
INSERT INTO #tests(date1, date2, result) VALUES
(/*Fri*/ '2021-01-01', /*Wed*/ '2020-01-01', /*Fri*/ '2020-01-03'),
(/*Sat*/ '2021-01-02', /*Thu*/ '2020-01-02', /*Sat*/ '2020-01-04'),
(/*Sun*/ '2021-01-03', /*Fri*/ '2020-01-03', /*Sun*/ '2020-01-05'),
(/*Mon*/ '2021-01-04', /*Sat*/ '2020-01-04', /*Mon*/ '2020-01-06'),
(/*Tue*/ '2021-01-05', /*Sun*/ '2020-01-05', /*Tue*/ '2020-01-07'),
(/*Wed*/ '2021-01-06', /*Mon*/ '2020-01-06', /*Wed*/ '2020-01-08'),
(/*Thu*/ '2021-01-07', /*Tue*/ '2020-01-07', /*Thu*/ '2020-01-09');
INSERT INTO #tests(date1, date2, result) VALUES
(/*Fri*/ '2021-01-01', /*Sun*/ '2017-01-01', /*Fri*/ '2016-12-30'),
(/*Sat*/ '2021-01-02', /*Mon*/ '2017-01-02', /*Sat*/ '2016-12-31'),
(/*Sun*/ '2021-01-03', /*Tue*/ '2017-01-03', /*Sun*/ '2017-01-01'),
(/*Mon*/ '2021-01-04', /*Wed*/ '2017-01-04', /*Mon*/ '2017-01-02'),
(/*Tue*/ '2021-01-05', /*Thu*/ '2017-01-05', /*Tue*/ '2017-01-03'),
(/*Wed*/ '2021-01-06', /*Fri*/ '2017-01-06', /*Wed*/ '2017-01-04'),
(/*Thu*/ '2021-01-07', /*Sat*/ '2017-01-07', /*Thu*/ '2017-01-05');
Advertisement
Answer
Assuming you can create/modify a calendar dimension, is this what you are after?
WITH
DAY_OF_WEEK_CALENDAR AS
( SELECT CAST('2021-04-01' AS DATE) AS date_id, 'Thursday' AS day_of_week UNION
SELECT CAST('2021-04-02' AS DATE), 'Friday' UNION
SELECT CAST('2021-04-03' AS DATE), 'Saturday' UNION
SELECT CAST('2021-04-04' AS DATE), 'Sunday' UNION
SELECT CAST('2021-04-05' AS DATE), 'Monday' UNION
SELECT CAST('2021-04-06' AS DATE), 'Tuesday' UNION
SELECT CAST('2021-04-07' AS DATE), 'Wednesday' UNION
SELECT CAST('2021-04-08' AS DATE), 'Thursday' UNION
SELECT CAST('2021-04-09' AS DATE), 'Friday' UNION
SELECT CAST('2021-04-10' AS DATE), 'Saturday' UNION
SELECT CAST('2021-04-11' AS DATE), 'Sunday' UNION
SELECT CAST('2021-04-12' AS DATE), 'Monday' UNION
SELECT CAST('2021-04-13' AS DATE), 'Tuesday' UNION
SELECT CAST('2021-04-14' AS DATE), 'Wednesday'
),
TEST AS
( SELECT CAST('2021-04-02' AS DATE) AS date_1,
CAST('2021-04-10' AS DATE) AS date_2
UNION
SELECT CAST('2021-04-04' AS DATE) AS date_1,
CAST('2021-04-10' AS DATE) AS date_2
)
SELECT TEST.*,
( SELECT TOP 1 date_id
FROM DAY_OF_WEEK_CALENDAR DOW_2
WHERE DOW_2.date_id BETWEEN DATEADD(day,-7,TEST.date_2)
AND DATEADD(day,7,TEST.date_2)
AND DOW_1.day_of_week = DOW_2.day_of_week
ORDER
BY DATEDIFF(day,DOW_2.date_id,TEST.date_2) ASC
) AS nearest_date_match
FROM TEST
INNER
JOIN DAY_OF_WEEK_CALENDAR DOW_1
ON TEST.date_1 = DOW_1.date_id