DECLARE @StartDate DATE = '2014-07-17';
SELECT *
FROM
(
--Show Closest Previous 2 Days Not In Friday or Saturday
SELECT TOP 2
DATEADD(DAY, -nr, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, -nr, @StartDate)) CheckName,
-nr CheckCount
FROM (VALUES(1),(2),(3),(4)) AS Numbers(nr)
WHERE DATENAME(DW, DATEADD(DAY, -nr, @StartDate)) NOT IN ('Friday','Saturday')
UNION ALL
--Show Todays Date If Not Friday or Saturday
SELECT TOP 1
DATEADD(DAY, +nr, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) CheckName,
nr CheckCount
FROM (VALUES(0)) AS Numbers(nr)
WHERE DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) NOT IN ('Friday','Saturday')
UNION ALL
--Show Closest Next 2 Days Not In Friday or Saturday
SELECT TOP 2
DATEADD(DAY, +nr, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) CheckName,
nr CheckCount
FROM (VALUES(1),(2),(3),(4)) AS Numbers(nr)
WHERE DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) NOT IN ('Friday','Saturday')
) d
ORDER BY d.CheckDate
I break it into 3 parts, previous 2 days, today (if applicable) and next 2 days
Here is the output:
CheckDate CheckName CheckCount
2014-07-15 Tuesday -2
2014-07-16 Wednesday -1
2014-07-17 Thursday 0
2014-07-20 Sunday 3
2014-07-21 Monday 4
I use the datename since not sure what @@datefirst your server is set to. the values() section is just a numbers table (you should create a numbers table as big as the amount of records you want to return plus any weekends you are crossing over) and then the TOP 2 in the first and last sections would be replaced with the number of days you wanted to return before and after.
**** Update with generic numbers table functionality added:
Here we declare the starting date and the number of previous and next days we would like to pull:
DECLARE @StartDate DATE = '2014-07-20';
DECLARE @MaxBusDays INT = 5
This next section creates a numbers table (can be easily found via google)
DECLARE @number_of_numbers INT = 100000;
;WITH
a AS (SELECT 1 AS i UNION ALL SELECT 1),
b AS (SELECT 1 AS i FROM a AS x, a AS y),
c AS (SELECT 1 AS i FROM b AS x, b AS y),
d AS (SELECT 1 AS i FROM c AS x, c AS y),
e AS (SELECT 1 AS i FROM d AS x, d AS y),
f AS (SELECT 1 AS i FROM e AS x, e AS y),
numbers AS
(
SELECT TOP(@number_of_numbers)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS number
FROM f
)
Now we use the numbers table and a row_number setting to pull only the number of rows before and after (plus the date of, if it's not fri/sat as wanted) that are working days (not fri/sat)
SELECT *
FROM
(
--Show Closest Previous x Working Days (Not Friday or Saturday)
SELECT * FROM
(
SELECT
DATEADD(DAY, -number, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, -number, @StartDate)) CheckName,
-number CheckCount,
ROW_NUMBER() OVER (ORDER BY number ASC) AS RowCounter
FROM Numbers
WHERE DATENAME(DW, DATEADD(DAY, -number, @StartDate)) NOT IN ('Friday','Saturday')
) a
WHERE a.RowCounter <= @MaxBusDays
UNION ALL
--Show Todays Date If Working Day (Not Friday or Saturday)
SELECT TOP 1
@StartDate CheckDate,
DATENAME(DW, @StartDate) CheckName,
0 CheckCount,
0 RowCounter
WHERE DATENAME(DW, @StartDate) NOT IN ('Friday','Saturday')
UNION ALL
--Show Closest Next x Working Days (Not Friday or Saturday)
SELECT * FROM
(
SELECT
DATEADD(DAY, +number, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, +number, @StartDate)) CheckName,
number CheckCount,
ROW_NUMBER() OVER (ORDER BY number ASC) AS RowCounter
FROM Numbers
WHERE DATENAME(DW, DATEADD(DAY, +number, @StartDate)) NOT IN ('Friday','Saturday')
) b
WHERE b.RowCounter <= @MaxBusDays
) c
ORDER BY c.CheckDate
Here is the output: (2014-07-20 is the middle row)
CheckDate CheckName CheckCount RowCounter
2014-07-13 Sunday -7 5
2014-07-14 Monday -6 4
2014-07-15 Tuesday -5 3
2014-07-16 Wednesday -4 2
2014-07-17 Thursday -3 1
2014-07-20 Sunday 0 0
2014-07-21 Monday 1 1
2014-07-22 Tuesday 2 2
2014-07-23 Wednesday 3 3
2014-07-24 Thursday 4 4
2014-07-27 Sunday 7 5
sql-server
tag based on provided code – a_horse_with_no_nameworking_day
/bit
column that's populated based on whatever rules make sense for you - i.e. if you also have rules about public holidays. – Damien_The_Unbeliever