T-SQL CTE Sequence of Weeks [closed] - tsql

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I am trying to write a recursive CTE to give me a sequence of Mondays starting at the 38th week for the next 20 weeks over 6 years. I need to graph weekly sales data for the past 6 years and thought a recursive CTE would be the best method to dynamically create a sequence of Monday dates. It's a little complicated because the season continues into the next year. Here's an example of how I would like the recordset to look:
9/17/2012
9/24/2012
10/1/2012
10/8/2012
10/15/2012
10/22/2012
10/29/2012
11/5/2012
11/12/2012
11/19/2012
11/26/2012
12/3/2012
12/10/2012
12/17/2012
12/24/2012
12/31/2012
1/7/2013
1/14/2013
1/21/2013
1/28/2013
2/4/2013
2/11/2013
2/18/2013
2/25/2013
9/16/2013 <-next season start
9/23/2013
9/30/2013
10/7/2013
10/14/2013
10/21/2013
10/28/2013
11/4/2013
11/11/2013
11/18/2013
11/25/2013
12/2/2013
12/9/2013
12/16/2013
12/23/2013
12/30/2013
1/6/2014
1/13/2014
1/20/2014
1/27/2014
2/3/2014
2/10/2014
2/17/2014
2/24/2014
I don't know if this is possible, but it seems like it could be. I was thinking I might have to use multiple CTEs to accomplish this, but am really struggling how to do this. Any help or guidance is greatly appreciated.

So I figured it out. valverij's answer would have worked as well. Here's what I came up with using 2 recursive CTE's. If anyone sees anything wrong with it, let me know.
WITH Seasons(StartDate) AS
(
SELECT DATEADD(m, 4, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)) AS StartDate UNION ALL
SELECT DATEADD(yy, -1, StartDate)
FROM Seasons
WHERE YEAR(StartDate) > YEAR(GETDATE()) - 6
),
Weeks(StartDate, WeekStartDate) AS
(
SELECT DATEADD(d, 1 - DATEPART(dw, DATEADD(wk, 20, Seasons.StartDate)), DATEADD(wk, 20, Seasons.StartDate)), DATEADD(d, 1 - DATEPART(dw, DATEADD(wk, 20, Seasons.StartDate)), DATEADD(wk, 20, Seasons.StartDate)) AS WeekStartDate
FROM Seasons UNION ALL
SELECT StartDate, DATEADD(wk, 1, WeekStartDate)
FROM Weeks
WHERE (WeekStartDate < DATEADD(wk, 23, StartDate))
)
SELECT StartDate, WeekStartDate
FROM Weeks
ORDER BY WeekStartDate DESC

If you're just looking for Mondays in a table, you can use DATENAME(WEEKDAY, [ColumnName]) to test for Mondays.
For example, the following code would find all of the Monday SaleDates in a hypothetical Sales table:
SELECT *
FROM Sales
WHERE DATENAME(WEEKDAY, SaleDate) = 'Monday'
From there, you could apply whatever additional conditions you need to (start date, end date, etc.)
Now, if you are just looking to generate a list of all Mondays, you can use a table variable and a WHILE loop:
DECLARE #Mondays TABLE(MondayDate datetime)
DECLARE #CurrentDate datetime = '02/07/2013' -- one year ago
WHILE #CurrentDate <= GETDATE() BEGIN
IF DATENAME(WEEKDAY, #CurrentDate) = 'Monday'
INSERT INTO #Mondays VALUES(#CurrentDate)
SET #CurrentDate = #CurrentDate + 1
END
SELECT *
FROM #Mondays
Either way, I definitely don't think you need CTE's to accomplish this.

Related

calculating last 5 years from current date in hive

I need to calculate some count based on the given time frame
I need to consider the dates between current date and last 5 years
select count(*) from table where (year(current_date) -year('2015-12-01')) < 5 ;
above query will give counts for last 5 years however it will consider only year part but I need exact counts considering days so if I write
select count(*) from table where datediff(current_date,final_dt) <= 1825 ;
it won't consider the leap years if any in the last 5 years
so Is there any function in hive to calculate exact difference between two dates consider scenarios like leap years?
Use add_months function (assuming the dates should go back to 2013-05-25 with the current date being 2018-05-25).
select count(*)
from table
where final_dt >= add_months(current_date,-60) and final_dt <= current_date
I think you are trying to calculate count(*) all records between current_date and a date which is 5 year in the past from current_date, in this case, you can do something like this:
SELECT count(*) FROM table_1 WHERE date_column BETWEEN current_date AND to_date(CONCAT(YEAR(current_date) - 5, '-', MONTH(current_date), '-', DAY(current_date)));
And SELECT datediff( current_date() ,to_date(CONCAT(YEAR(current_date) - 5, '-', MONTH(current_date), '-', DAY(current_date))));
gives you 1826 (considering the fact that 2016 is a leap year).

Create buffers postgis table from points using date filter

I,m trying to create view or table where are polygons generated from point buffers and group all polygons based on year.
Data fields from source table:
point_id(int), point_created(date), geom geometry(Point,3301)
1, 2014-05-09, point
2, 2015-01-01, point
2, 2015-02-05, point
3, 2016-02-05, point
4, 2017-02-10, point
I was able to create table where I grouped all points by year and generated buffer as multipolygon but what I need is to group point based on date between years(group more than one year points together), so table must look like:
polygon(geom), nr_of_features(int), year(string)
1, 1, 2014(all point from 2014)
2, 3, 2015(all points from 2014 to 2015)
3, 4, 2016(all points from 2014 to 2016)
4, 5, 2017(all points from 2014 to 2017)
Script I,m using right now:
CREATE TABLE my_new_table as
SELECT ST_Union(ST_Buffer(geom,10))::geometry(MultiPolygon,3301) as polygon,count(point_id)::integer as nr_of_features,
extract(year from point_created) as year
FROM my_table
group by year;
Any help is welcome.
If I understand you correctly you need something like that:
--just for create few years
WITH RECURSIVE dates AS (
SELECT '2014-12-31'::timestamp years
UNION ALL
SELECT years + interval '1 year' FROM dates WHERE years < '2019-12-31'
)
SELECT
EXTRACT(YEAR FROM d.years) years,
p.*
FROM
points p
INNER JOIN
dates d ON p.date <= d.years
;
Now you can use the years column to aggregate the points.
I had to modify this script a little because point dates is between 1994 and current date, so I changed you sample value '2014-12-31' to 2013-12-31 and '2019-12-31' to current_date. It seems working now, thanks you. I have 13000 points and it takes 173msec to create table using this query:
WITH RECURSIVE dates AS (
SELECT '1993-12-31'::timestamp years
UNION ALL
SELECT years + interval '1 year' FROM dates WHERE years < current_date
)
SELECT
EXTRACT(YEAR FROM d.years) years,
ST_Multi(ST_Collect(geom))::geometry(MultiPoint,3301) as polygon, count(years)::int as nr_features
FROM
my_table p
INNER JOIN
dates d ON p.point_created <= d.years
group by years
order by years asc;

Getting Dates by Selecting a week in oracle

I have a textbox with random numbers from 1 to 52 which are week numbers of a calendar and a drop down which mentions as years.
For example if I select 2 in a textbox with year 2014, then I want the dates to be mentioned as 05-1-2014 - 11-1-2014. Is it possible to do it.
Also I have tried one query which doesnt match my requirement
SELECT date_val, TO_CHAR (date_val, 'ww')
FROM (SELECT TO_DATE ('01-jan-2013', 'DD-MON-YYYY') + LEVEL AS date_val
FROM DUAL
CONNECT BY LEVEL <= 365)
Please help.
Try this. Here 2 is the number of week in the year (FirstSunday+(NumberOfWeek-1)*7 as WeekStart, FirstSunday+ NumberOfWeek*7-1 as WeekEnd) and 2014 is a year:
select
FirstSunday+(2-1)*7 as WeekStart,
FirstSunday+ 2*7-1 as WeekEnd
from
(
Select NEXT_DAY(TO_DATE('01/01/'||'2014','DD/MM/YYYY')-7, 'SUN') as FirstSunday
from dual
)
SQLFiddle demo
Try this too,
SELECT start_date,
start_date + 6 end_day
FROM(
SELECT TRUNC(Trunc(to_date('2014', 'YYYY'),'YYYY')+ 1 * 7,'IW')-1 start_date
FROM duaL
);

Always return data from last week's Monday thru Sunday

How to write a sql statement that always returns data from last Monday to the last Sunday? Any guidance is appreciated.
Thanks.
t-clausen.dk's answer does work, but it may not be clear why it works (neither to you nor to the developer who comes after you). Since added clarity sometimes comes at the cost of conciseness and performance, I'd like to explain why it works in case you'd prefer to use that shorter syntax.
SELECT t.*
FROM <table> t CROSS JOIN
(SELECT DATEDIFF(day, 0, getdate() - DATEDIFF(day, 0, getdate()) %7) lastmonday) a
WHERE t.yourdate >= a.lastmonday - 7 and yourdate < a.lastmonday
How SQL Server Stores datetime Internally
SQL Server stores datetime as two 4-byte integers; the first four bytes represents the number of days since 1/1/1900 (or before 1/1/1900, for negative numbers) and the second four bytes represents the number of milliseconds since midnight.
Using datetime with int or decimal
Because datetime is stored as two 4-byte integers, it is easy to move between numeric and date data types in T-SQL. For example, SELECT GETDATE() + 1 returns the same as SELECT DATEADD(day, 1, GETDATE()), and CAST(40777.44281 AS datetime) is the same as 2011-08-24 10:37:38.783.
1/1/1900
Since the first integer portion of datetime is, as was mentioned above, the number of days since 1/1/1900 (also called the SQL Server Epoch), CAST(0 as datetime) is by definition equivalent to
1900-01-01 00:00:00
DATEDIFF(day, 0, GETDATE())
Here's where things start to get both tricky and fun. First, we've already established that when 0 is treated as a date, it's the same as 1/1/1900, so DATEDIFF(day, '1/1/1900', GETDATE()) is the same as DATEDIFF(day, 0, GETDATE())—both will return the current number of days since 1/1/1900. But, wait: the current number of days is exactly what is represented by the first four bytes of datetime! In a single statement we have done two things: 1) we've removed the "time" portion returned by GETDATE() and we've got an integer value we can use to make the calculation for finding the most recent Sunday and the previous Monday a little easier.
Modulo 7 for Monday
DATEDIFF(day, 0, GETDATE()) % 7 takes advantage of the fact that DATEPART(day, 0) (which, at the risk of overemphasizing the point, is the same as DATEPART(day, '1/1/1900')) returns 2 (Monday).1 Therefore, DATEDIFF(day, 0, GETDATE()) % 7 will always yield the number of days from Monday for the current date.
1 Unless you have changed the default behavior by using DATEFIRST.
Most Recent Monday
It's almost too trivial for its own heading, but at this point we can put together everything we've got so far:
GETDATE() - DATEDIFF(day, 0, GETDATE()) %7 gives you the most recent Monday
DATEDIFF(day, 0, GETDATE() - DATEDIFF(day, 0, GETDATE()) %7) gives you the most recent Monday as a whole date, with no time portion.
But the poster wanted everything from Monday to Sunday...
Instead of using the BETWEEN operator, which is inclusive, the posted answer excluded the last day, so that there was no need to do any shifting or calculating to get the right date range:
t.yourdate >= a.lastmonday - 7 returns records with dates since (or including) midnight on the second-most-recent Monday
t.yourdate < a.lastmonday returns records with dates before (but not including) midnight on the most recent Monday.
I am a big proponent of writing code that is easy to understand, both for you and for the developer who comes after you a year later (which might also be you). I believe that the answer I posted earlier should be understandable even to novice T-SQL programmers. However, t-clausen.dk's answer is concise, performs well, and could be encountered in production code, so I wanted to give some explanation to help future visitors understand why it works.
I realized my code was too complex, so I changed my answer to this. The minus one after getdate() corrects this to return the last Monday on Sunday instead of this weeks Monday (tomorrow if today is Sunday).
SELECT t.*
FROM <table> t CROSS JOIN
(SELECT DATEDIFF(week, 0, getdate() - 1) * 7 lastmonday) a
WHERE t.yourdate >= a.lastmonday - 7 and yourdate < a.lastmonday
Old code
SELECT t.*
FROM <table> t CROSS JOIN
(SELECT DATEDIFF(day, 0, getdate() - DATEDIFF(day, 0, getdate()) %7) lastmonday) a
WHERE t.yourdate >= a.lastmonday - 7 and yourdate < a.lastmonday
You did not specify which SQL dialect, so I will answer for T-SQL, which is what I know best, and you've used the tsql tag.
In T-SQL, use the DATEPART function to find the day of the week. When you know the current day of the week, you can get the date of the most recent Sunday and the Monday before it.
In a stored procedure, it's easier—at least, more readable and easier to maintain, in my opinion—to calculate the values for the most recent Sunday and the preceding Monday and store the values in variables. Then those variables can be used in calculations later in the procedure.
CREATE PROCEDURE SomeProcedure
AS
DECLARE #CurrentDayOfWeek int, #LastSunday date, #LastMonday date
SET #CurrentWeekday = DATEPART(weekday, GETDATE())
-- Count backwards from today to get to the most recent Sunday.
-- (#CurrentWeekday % 7) - 1 will give the number of days since Sunday;
-- -1 negates for subtraction.
SET #LastSunday = DATEADD(day, -1 * (( #CurrentWeekday % 7) - 1), GETDATE())
-- Preceding Monday is obviously six days before last Sunday.
SET #LastMonday = DATEADD(day, -6, #LastSunday)
SELECT ReportColumn1, ReportColumn2
FROM ReportTable
WHERE DateColumn BETWEEN #LastMonday AND #LastSunday
If you need to be able to do the calculation in a SELECT statement or a view, it's trivial now that we've worked out the steps, though the query itself is a little messier:
SELECT ReportColumn1, ReportColumn2
FROM ReportTable
WHERE DateColumn
BETWEEN
(
-- Last Monday is six days before...
DATEADD(day, -6,
-- ... last Sunday.
DATEADD(day, -1 * (( DATEPART(weekday, GETDATE()) % 7) - 1), GETDATE())
)
)
AND
(
-- Last Sunday has to be calculated again each time it is used inline.
DATEADD(day, -1 * (( DATEPART(weekday, GETDATE()) % 7) - 1), GETDATE())
)
The parentheses I added are not necessary, but are only there to help you see how the WHERE clause is built.
Finally, note that these use the SQL 2008 date data type; for the datetime data type, you may need to perform your own conversion/truncation to compare whole dates instead of date-plus-time values.
The short code in #t-clausen.dk answer doesn't work for Sunday nor does the first result I found on Google. To test them out, try.
DECLARE #date as DATETIME;
SET #date = '2014-11-23 10:00:00'; -- Sunday at 10a
SELECT DATEADD(wk, DATEDIFF(wk,0,#date), 0) -- 2014-11-24 00:00:00
SELECT CAST(DATEDIFF(week, 0, #date)*7 as datetime) -- 2014-11-24 00:00:00
SELECT CAST(DATEDIFF(day, 0, CAST(#date as DATETIME) - DATEDIFF(day, 0,#date) %7) as DATETIME) --2014-11-17 00:00:00
SELECT DATEADD(wk, DATEDIFF(wk,0,#date-1), 0) --2014-11-17 00:00:00
Thus, you should use the long code from the original answer or modified short code.
SELECT t.*
FROM <table> t CROSS JOIN
(SELECT DATEDIFF(week, 0, getdate() - 1) * 7 lastmonday) a
WHERE t.yourdate >= a.lastmonday - 7 and yourdate < a.lastmonday

Calculate working days - Monday to Fri in Tsql

How can i calculate the last working five days which is monday to Friday. my current script gets the last monday's date, but i cannot get the last friday's date. Please help
declare #StartDate datetime
declare #EndDate datetime
--Calculate date range for report
select #EndDate = Cast(convert(char(10), getdate(), 101)+' 00:00:00' as datetime)
select #StartDate = DateAdd(d, -7, #EndDate)
select #EndDate = Cast(convert(char(10), getdate(), 101)+' 23:59:59' as datetime)
select #StartDate startdate
select #EndDate enddate
Datepart offers you an easy way to get the week day:
SET DATEFIRST 1 -- monday is first day of the week
SELECT DATEPART(weekday, '20110725')
-- result is 1
See T-SQL Date functions and SET DATEFIRST for more information.
Using the weekday, you can work out how many days ago last monday and friday are and use 'AddDate' (like you are doing now) to calculate those.
Note that you should really use DATEDIFF for this type of date range selection. If you select everything up to 23:59:59 there's always a chance that some records are left out. For example 23:59:59.001 is out of range but it's still on the same day. With DATEDIFF you can test whether it's on the same day, discarding the time part. No need to bother with casting to string, adding time and casting back.
The answer is more complex than people are assuming. What you need is to go 5 days back and find the first monday before that, and the first friday after that. You can eather use ##datefirst, a calculation or 'set firstdate 1' for that. I prefer not using the last one, because it can't be done in functions. As you can see i used the calculation, ##datefirst is just as good.
Assuming you want the last group of monday to friday that is in the past. This query will get that. If you trust your current monday, you can just add 5 days and subtract 1 minute (I wouldn't trust it, it only returns last monday if you run the query on a monday).
In my sql, I am not aiming for simplicity, I am aiming for effectivity.
DECLARE #getdate datetime = dateadd(day, cast(getdate() as int), 0)
-- the 'Declare' can also be written like this thanks to #Andriy M
--DECLARE #getdate = CAST(GETDATE() - 0.5 AS int)
SELECT #getdate - 5 - CAST(#getdate- 5 as int) % 7 monday,
dateadd(minute, -1, #getdate) - CAST(#getdate- 5 as int) % 7 friday
Result:
Monday Friday
2011-07-18 0:00:00 2011-07-22 23:59:00
*first solution was a day off #AndriyM pointed it out, it has been solved.
Answer to #Andriy M
For some reason it acted different than I expected. I can't explain it but try this
select cast(dateadd(day, cast(getdate() as int) - .5, 0) as datetime),
cast(dateadd(day, cast(getdate() as int), 0) as datetime),
cast(dateadd(day, cast(getdate() as int) + .5, 0) as datetime)
in the morning the last 2 fields has same value, in the evening the first 2 fields has the same value. I am as surprised as you are, I wish I could explain it. It was tested here
https://data.stackexchange.com/stackoverflow/query/new
These two questions:
Find last sunday
How to get last day of last week in sql?
might be of some help.
Although, if you already know how to find the last Monday, you can easily find the corresponding Friday by adding 4 days to the Monday date using the DATEADD() function. For example:
SELECT #EndDate = DATEADD(DAY, 4, #StartDate)
It's all relative to TODAY's date, right?
So find out what today is DATEPART(weekday, getdate())
And then turn that into an adjustment variable -- e.g.:
declare #adjustment int
set #adjustment = CASE DATEPART(weekday, getdate()) WHEN 'MONDAY' THEN 0 WHEN 'TUESDAY' THEN 1, ...END
So then the Monday you want would be today - 7 - #adjustment
...and the Friday you want would be Monday + 5
Declare #myMonday smalldatetime,
#myFriday smalldatetime
set #myMonday = getdate() - 7 - #adjustment
set #myFriday = #myMonday + 5
DECLARE #my int
DECLARE #myDeduct int
DECLARE #day INT
DECLARE #mydate DATETIME
SET #mydate = '2012-08-01'
SET #myDeduct = 0
SET DateFirst 1 -- Set it monday=1 (value)
--Saturday and Sunday on the first and last day of a month will Deduct 1
IF (DATEPART(weekday,(DATEADD(dd,-(DAY(#mydate)-1),#mydate))) > 5)
SET #myDeduct = #myDeduct + 1
IF (DATEPART(weekday,(DATEADD(dd,-(DAY(DATEADD(mm,1,#mydate))),DATEADD(mm,1,#mydate)))) > 5)
SET #myDeduct = #myDeduct + 1
SET #my = day(DATEADD(dd,-(DAY(DATEADD(mm,1,#mydate))),DATEADD(mm,1,#mydate)))
select (((#my/7) * 5 + (#my%7)) - #myDeduct) as Working_Day_per_month
I'll throw my hat in the ring too. :-)
DECLARE #Date datetime = '01/11/2015'
DECLARE #StartDate datetime = DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6) -- MONDAY
DECLARE #EndDate datetime = DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6) -- FRIDAY
SELECT '#Date' as Variable ,CONVERT(date, #Date) as DateValue ,DATENAME(dw, #Date) as DayOfTheWeek
UNION SELECT '#StartDate' as Variable ,CONVERT(date, #StartDate) as DateValue ,DATENAME(dw, #StartDate) as DayOfTheWeek
UNION SELECT '#EndDate' as Variable ,CONVERT(date, #EndDate) as DateValue ,DATENAME(dw, #EndDate) as DayOfTheWeek
-- Variable DateValue DayOfTheWeek
-- ---------- ---------- ------------
-- #Date 2015-01-11 Sunday
-- #StartDate 2015-01-05 Monday
-- #EndDate 2015-01-09 Friday
BONUS: Here you can generate a quick table of the 5 weekdays using the same technique.
SELECT DATENAME(dw, DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6))) as DayOfTheWeek
, DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6)) as DateValue
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT
-- DayOfTheWeek DateValue
-- ------------------------------ -----------------------
-- Monday 2015-01-05 00:00:00.000
-- Tuesday 2015-01-06 00:00:00.000
-- Wednesday 2015-01-07 00:00:00.000
-- Thursday 2015-01-08 00:00:00.000
-- Friday 2015-01-09 00:00:00.000
Here's an explanation:
1) First we need to know what date to begin our evaluation from. For this example, we chose to use Sunday, January 11th, 2015.
DECLARE #Date2 datetime = '01/11/2015'
1b) Here's a nice to have bonus technique of getting the name for the day of the week, given a date value
SELECT #Date2 as DateValue, DATENAME(dw, #Date2) as DayOfTheWeek
2) Next we need to know deterministically (based on the US calendar) what the given day of the week is numerically between 1 and 7
NOTE: 1899.12.31 is the first Sunday before 1900.01.01, which is the MINIMUM value for the SmallDateTime data type.
NOTE: Yes, you could use DATEPART(dw, #Date) like this more simply, but it is not deterministic given that certain server environments could have different configurations
RESULTS: 1 = Sunday | 2 = Monday | 3 = Tuesday | 4 = Wednesday | 5 = Thursday | 6 = Friday | 7 = Saturday
SELECT ((DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date2) % 7) + 1) [DayOfWeek Deterministic (Based on US)]
3) Now, given any date, you should have a deterministic way of determining the Monday for that given week
SELECT DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date2) % 7)), #Date2) as [Monday Day of the Week - Deterministic (Based on US)]
4) Now, given any date, you should have a deterministic way of determining the Friday for that given week
SELECT DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date2) % 7)), #Date2) as [Monday Day of the Week - Deterministic (Based on US)]
5) The last date manipulation technique we need is to know how to get into a week that has the first full week of weekdays happening before it. For instance, if we are on a Sunday and we subtract 1 day from it, then we get to Saturday, which puts us in the previous week, which is the first full week of weekdays. Alternatively, if we also subtracted 1 day from Monday, it would only get us to Sunday, which is not the previous week, so subtracting 1 day is not enough. On the flip side, if we were on a Saturday and subtracted 7 days, it would take us past the previous full week of weekday, into the week before it, which is too far. Here's a run down of the analysis to figure out what the magic numbers is that you can subtract by that will work with any day of the week. As you can see below, the magic number is 6.
-- DAYS TO SUBTRACT
-- Day of the Week - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7
-- =============== ==== ==== ==== ==== ==== ==== ==== ====
-- Sunday Bad Good Good Good Good Good Good Good
-- Monday Bad Bad Good Good Good Good Good Good
-- Tuesday Bad Bad Bad Good Good Good Good Good
-- Wednesday Bad Bad Bad Bad Good Good Good Good
-- Thursday Bad Bad Bad Bad Bad Good Good Good
-- Friday Bad Bad Bad Bad Bad Bad Good Good
-- Saturday Good Good Good Good Good Good Good Bad
BONUS) If you want to have all the weekdays in little table, then you would want to also use a quick zero based "tally table". There are many ways to do this, so pick your flavor. Here are few.
SELECT * FROM (SELECT 0 as DaysToAdd UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) as TT
SELECT * FROM (SELECT TOP 5 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM sys.all_columns a CROSS JOIN sys.all_columns b) as TT
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT