Get weekends between two dates [duplicate] - sql

This question already has answers here:
Get number of weekends between two dates in SQL
(5 answers)
Closed 7 years ago.
I have done the following so far:
declare #date int=7
declare #curDate date=getdate()
create table #temp(dat date,day1 varchar(max))
while #date>0
begin
insert into #temp values(#curDate,DATENAME(DW,#curDate))
set #curDate=DATEADD(Day,-1,#curDate)
if(DATENAME(DW,#curDate)<>'Saturday' and DATENAME(DW,#curDate)<>'Sunday')
begin
set #date=#date-1
end
End
select * from #temp
By this code i can easily find if there is a weekend between two date or not.
My question is:
Is there any other way to find if between two dates got a weekend or
not
e.g
date1 '03-25-2015' and date2 '03-30-2015' got a weekend or not??
Example/Expected Output:
table1
(
id bigint,
value1 varchar(50),
value2 decimal(18,2),
.
.
.
date1 date
)
let passdate1(firstdate(min)) and passdate2(last date (max)) is two
given date:
I want it like this:
select * from table1 where date1 between case
when (passdate1,passdate2) has weekend and it's no is 2 days
then passdate1 and dateadd(day,2,passdate2)
else
passdate1 and passdate2 end

Use recursive common table expressions to select all dates, then use DATEPART to determine if each date is a weekend
;WITH dates AS (
SELECT CONVERT( DATE, '2015-01-01' ) AS a
UNION ALL
SELECT DATEADD( DAY, 1, a )
FROM dates
WHERE DATEADD( DAY, 1, a ) < '2015-02-01'
)
SELECT a
FROM dates
WHERE DATEPART( dw, a ) IN ( 1, 7 )

Define "between". Does it have to be a full two-day weekend? Are the endpoints ever weekend days themselves? Are the endpoint dates ever the same?
I'm not quite sure how you're using the code above. You could possibly check that (select count(*) from #temp) < datediff(dd, #date1, #date2) but I don't get the impression you had that in mind.
Does this work for you? It would detect a full weekend when #date1 and #date2 are always weekdays.
datediff(dd, #date1, #date) > 5 or datepart(dw, #date2) < datepart(dw, #date1)
I'm assuming a weekend of Saturday and Sunday with day numbering that begins on Sunday.

Try this:
DECLARE #sd DATE = '20150326', #ed DATE = '20150329'
IF DATEDIFF(dd, #sd, #ed) >= 7 OR ( DATEPART(dw, #sd) = 7 AND DATEPART(dw, #ed) = 1 )
OR ( DATEDIFF(dd, #sd, #ed) >= 2 AND DATEPART(dw, #sd) > DATEPART(dw, #ed) )
PRINT 'YES'
ELSE
PRINT 'NO'

Try this solution which, essentially, computes difference in weeks between two dates and if those dates are equals it returns 0:
SELECT *,
DATEDIFF(WEEK, StartDate, EndDate) AS NumOfWeekends
FROM (VALUES
('2015-03-03', '2015-03-25'),
('2015-03-03', '2015-03-03'),
('2015-03-03', '2015-03-07'),
('2015-03-03', '2015-03-08'),
('2015-03-07', '2015-03-08'),
('2015-03-07', '2015-03-07'),
('2015-03-08', '2015-03-08'),
('2015-03-03', NULL)
) x(StartDate, EndDate);
/*
Output:
StartDate EndDate NumOfWeekends
---------- ---------- -------------
2015-03-03 2015-03-25 3
2015-03-03 2015-03-03 0
2015-03-03 2015-03-07 0
2015-03-03 2015-03-08 1
2015-03-07 2015-03-08 1
2015-03-07 2015-03-07 0
2015-03-08 2015-03-08 0
2015-03-03 NULL NULL
*/
Note: DATEDIFF(WEEK isn't dependent on ##DATEFIRST setting according to this.

Related

reporting Wednesday to wednesday

I am trying run a report based on a Wednesday to Wednesday reporting week.
I have found lots of examples that say the get correct date, such as:
DATEADD(DAY, -5, DATEADD(WEEK, DATEDIFF(WEEK, 0, getdate()), 0))
The problem is that these seem to only work for the current week. The example above gives 15/11/17 which is correct for today (24/11/2017) but incorrect on Sunday (26/11/2017) when it would get the 22/11/2017.
if I look at the report between 22-28/11/2017(Wed-Tue) I should see a report from 15-22/11/2017
Between the 29/11 & 5/12/2017 the report should be from 22-29/11/2017
any help is appreciated!
Try this method
SELECT
*,
CASE WHEN [wensday]>reportDate THEN DATEADD(WEEK,-2,[wensday]) ELSE DATEADD(WEEK,-1,[wensday]) END [from date],
CASE WHEN [wensday]>reportDate THEN DATEADD(WEEK,-1,[wensday]) ELSE [wensday] END [to date]
FROM
(
SELECT
reportDate,
-- monday of this week
--DATEADD(DAY,DATEDIFF(DAY,0,reportDate)/7*7,0) [monday],
-- wensday of this week
DATEADD(DAY,2,DATEADD(DAY,DATEDIFF(DAY,0,reportDate)/7*7,0)) [wensday]
FROM
(
SELECT CAST('20171115' AS date) reportDate
UNION ALL
SELECT CAST('20171121' AS date) reportDate
UNION ALL
SELECT CAST('20171122' AS date) reportDate
UNION ALL
SELECT CAST('20171123' AS date) reportDate
UNION ALL
SELECT CAST('20171124' AS date) reportDate
UNION ALL
SELECT CAST('20171129' AS date) reportDate
UNION ALL
SELECT CAST('20171205' AS date) reportDate
) test
) q
The inline algorithm
DECLARE #reportDate date=GETDATE()
DECLARE #Wensday date=DATEADD(DAY,2,DATEADD(DAY,DATEDIFF(DAY,0,#reportDate)/7*7,0))
DECLARE #FromDate date=CASE WHEN #Wensday>#reportDate THEN DATEADD(WEEK,-2,#Wensday) ELSE DATEADD(WEEK,-1,#Wensday) END
DECLARE #ToDate date=DATEADD(WEEK,1,#FromDate)
SELECT #reportDate,#Wensday,#FromDate,#ToDate
You can use DATEFIRST to assign days 1-7 to Wed - Tue
Whatever date you put in here, it will return the first prior Wednesday
The following Tuesday is just 6 days after that.
-- Wednesday will be 1 when we use datepart dw
SET DATEFIRST 3;
DECLARE #ReportDate DATE
SET #ReportDate = '2017-11-26'
SELECT
DATEADD( d,
-(DATEPART(dw,#ReportDate)-1),
#ReportDate
)
Try this...
DECLARE #fDt as date,#fDtR as date
set #fDt = '11/15/2017'
SET DATEFIRST 3
SELECT #fDtR = DATEADD(d,-6-(DATEPART(dw,#fDt)),#fDt)
print #fDtR
you can try this
select * from youtablename where yourdatefield <=
dateadd(dd,datediff(dd,0,getdate())/7 * 7 + 2,0)) and yourdatefield >
dateadd(dd,datediff(dd,0,getdate())/7 * 7 + 2,-7))
From this you will get last wednesday
select
dateadd(dd,datediff(dd,0,getdate())/7 * 7 + 2,0))
and from this you will get last to last wednesday
select dateadd(dd,datediff(dd,0,getdate())/7 * 7 + 2,-7))
so that you can find Wednesday to Wednesday data.

SQL function for last 12 months

I am looking for a SQL-function that gives the last 12 months with Start Date and End Date. Say you pick 10.Dec, it will give a result in:
- StartDate -- EndDate
- 2013-11-01 - 2013-11-30
- 2013-10-01 - 2013-10-31
- 2013-09-01 - 2013-09-30
and so it goes for the last 12 months.
I tried modifying an old function we had, but I got totally off and confused in the end.
ALTER FUNCTION [dbo].[Last12Months](#Date date) RETURNS TABLE
AS
Return
(
with cte as (
SELECT DATEADD(mm, DATEDIFF(mm, 01, #Date), 01) AS Start,
DATEADD(mm, DATEDIFF(mm, -12, #Date), -12) AS EndDate
union all
select Start - 1, EndDate - 1 from cte
where Start >= #Date )
select CAST(Start as DATE) StartDate, CAST(EndDate as DATE) EndDate from cte)
Runned it like this:
select * from dbo.Last12Months ('2013-12-10')
and got:
- StartDate - EndDate
- 2013-12-02 - 2013-12-20
Anyone know what to do?
Please try using CTE:
ALTER FUNCTION [dbo].[Last12Months]
(
#Date datetime
) RETURNS #tbl TABLE (Start datetime, EndDate datetime)
AS
BEGIN
WITH T AS(
SELECT
DATEADD(month, DATEDIFF(month, 0, #Date), 0) AS Start,
DATEADD(d, -DAY(DATEADD(m,1,#date)),DATEADD(m,1,#date)) AS EndDate,
12 Cnt
UNION ALL
SELECT
DATEADD(month, -1, Start),
DATEADD(d, -DAY(DATEADD(m,1,Start-1)),DATEADD(m,1,Start-1)),
Cnt-1
FROM
T
WHERE
Cnt-1>0
)
INSERT INTO #tbl
(Start, EndDate)
SELECT
Start, EndDate
FROM T
RETURN
END
This seems to do the job - whether you want to put it in a function or just wherever you need to have the data:
; With Numbers as (
select ROW_NUMBER() OVER (ORDER BY number ) as n
from master..spt_values
), Months as (
select DATEADD(month,n,'20010101') as start_date,
DATEADD(month,n,'20010131') as end_date
from Numbers
)
select * from Months
where DATEDIFF(month,start_date,GETDATE()) between 0 and 11
(Substitute any other date for GETDATE() if you want to get it based on some other date)
(On my machine, this can generate any month from January 2001 on to at least the next century - it can be adjusted if you need earlier or later dates also)
Damn, you've got to be quick on SO!
Good use of CTEs: i've learnt a bit answering this...
alter function Last12Months(#d date) returns table
as
return(
with cte as (
select
dateadd(month, datepart(mm,#d)-13,
dateadd(year,datepart(yyyy,#d)-1900,0)
)
as start
union all
select dateadd(mm, 1, start) from cte
where start < #d)
select start, dateadd(mm, 1, start) ends from cte
where start < #d
)
go
select * from Last12Months('2014-06-04')
Removed conversion to varchar thanks to
Date serial in SQL?
This returns 13 months: from say June last year to this June, inclusive.
To return the previous 12 months, not including the current June, change the final start<#d to
where start < dateadd(month, datepart(mm,#d)-1,
dateadd(year,datepart(yyyy,#d)-1900,0))
The end is 00:00 hours on the first day of the next month.
check this,
Declare #i date='2013-12-10'
;with cte as
(Select dateadd(month,datediff(month,0,#i)-1,0) StartDate
,dateadd(day,-1,dateadd(month,datediff(month,0,#i),0)) EndDate ,1 rownum
Union all
select dateadd(month,-1,StartDate),dateadd(day,-1,StartDate),rownum+1 rownum from cte where rownum<12 )
select * from cte
#Lebowski Below script will give you start and end date of specified calendar months from today in chronological order
DECLARE #nMonths TINYINT
SET #nMonths = 60
SELECT FORMAT(DATEADD(month, n.n - #nMonths+1+ DATEDIFF(month, 0, GETDATE()) -1 ,0), 'yyyy-MM-dd') AS MonthStartDate
, FORMAT(DATEADD(dd, -1, DATEADD(month, n.n - #nMonths+1 + DATEDIFF(month, 0, GETDATE()),0)), 'yyyy-MM-dd') AS MonthEndDate
FROM (SELECT TOP(#nMonths) n = ROW_NUMBER() OVER (ORDER BY NAME)
FROM master.dbo.syscolumns) n
Sample output
MonthStartDate MonthEndDate
2011-04-01 2011-04-30
2011-05-01 2011-05-31
2011-06-01 2011-06-30
2011-07-01 2011-07-31
2011-08-01 2011-08-31
2011-09-01 2011-09-30
2011-10-01 2011-10-31
2011-11-01 2011-11-30
2011-12-01 2011-12-31
....
Try this it might help you
select top 12 *
from YourTable
where dateOf between #DateFrom and #DateTo
order by dateOf desc

tsql: How to retrieve the last date of each month between given date range

I have two date for example 08/08/2013 and 11/11/2013 and I need last date of each month starting from August to November in a table so that i can iterate over the table to pick those dates individually.
I know how to pick last date for any month but i am stucked with a date range.
kindly help, it will be highly appreciated.
Note : I am using Sql 2008 and date rang could be 1 month , 2 month or 6 month or a year or max too..
You can use CTE for getting all last days of the month within the defined range
Declare #Start datetime
Declare #End datetime
Select #Start = '20130808'
Select #End = '20131111'
;With CTE as
(
Select #Start as Date,Case When DatePart(mm,#Start)<>DatePart(mm,#Start+1) then 1 else 0 end as [Last]
UNION ALL
Select Date+1,Case When DatePart(mm,Date+1)<>DatePart(mm,Date+2) then 1 else 0 end from CTE
Where Date<#End
)
Select * from CTE
where [Last]=1 OPTION ( MAXRECURSION 0 )
DECLARE #tmpTable table (LastDates DATE);
DECLARE #startDate DATE = '01/01/2012'; --1 Jan 2012
DECLARE #endDate DATE = '05/31/2012'; --31 May 2012
DECLARE #tmpEndDate DATE;
SET #startDate = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#startDate)+1,1));
SET #tmpEndDate = DATEADD(DAY, 1, #endDate);
WHILE (#startDate <= #tmpEndDate)
BEGIN
INSERT INTO #tmpTable (LastDates) values (DATEADD(DAY, -1, #startDate));
SET #startDate = DATEADD(MONTH, 1, #startDate);
END
SELECT [LastDates] FROM #tmpTable;
Output:
Example: 1
#startDate DATE = '01/01/2012'; --1 Jan 2012
#endDate DATE = '05/31/2012'; --31 May 2012
LastDates
----------
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31
Example: 2
#startDate DATE = '11/01/2011'; --1 Nov 2011
#endDate DATE = '03/13/2012'; --13 Mar 2012
LastDates
----------
2011-11-30
2011-12-31
2012-01-31
2012-02-29
I've created a table variable, filled it with all days between #startDate and #endDate and searched for max date in the month.
declare #tmpTable table (dates date)
declare #startDate date = '08/08/2013'
declare #endDate date = '11/11/2013'
while #startDate <= #endDate
begin
insert into #tmpTable (dates) values (#startDate)
set #startDate = DATEADD(DAY, 1, #startDate)
end
select max(dates) as [Last day] from #tmpTable as o
group by datepart(YEAR, dates), datepart(MONTH, dates)
Results:
Last day
2013-08-31
2013-09-30
2013-10-31
2013-11-11
To also get last day of November this can be used before loop:
set #endDate = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, #endDate) + 1, 0))
Following script demonstrates the script to find last day of previous, current and next month.
----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth
If you want to find last day of month of any day specified use following script.
--Last Day of Any Month and Year
DECLARE #dtDate DATETIME
SET #dtDate = '8/18/2007'
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#dtDate)+1,0))
LastDay_AnyMonth
ResultSet:
LastDay_AnyMonth
Source - SQL Server Central.
You can use a recursive CTE to do this, note the MAXRECURSION OPTION prevents an infinite loop:
DECLARE #StartDate DATE = '2013-08-08'
DECLARE #EndDate DATE = '2013-11-11'
;WITH dateCTE
AS
(
SELECT CAST(DATEADD(M, 1,DATEADD(d, DAY(#StartDate) * -1, #StartDate)) AS DATE) EndOFMonth
UNION ALL
SELECT CAST(DATEADD(M, 2,DATEADD(d, DAY(EndOFMonth) * -1, EndOFMonth)) AS DATE)
FROM dateCTE
WHERE EndOFMonth < DATEADD(d, DAY(#EndDate) * -1, #EndDate)
)
SELECT *
FROM dateCTE
OPTION (MAXRECURSION 30);
This returns
EndOFMonth
----------
2013-08-31
2013-09-30
2013-10-31
try this
the last row(where) is optional for date filtering
declare #table table
(
thisdate date
)
insert into #table values ('12/01/2013'),('05/06/2013'),('04/29/2013'),('02/20/2013')
select *,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,thisdate)+1,0))
LastDay from #table
where thisdate between 'givendate' and 'givendate'
The Example Below is for all dates
thisdate lastday
2013-12-01 2013-12-31 23:59:59.000
2013-05-06 2013-05-31 23:59:59.000
2013-04-29 2013-04-30 23:59:59.000
2013-02-20 2013-02-28 23:59:59.000
The following CTE gives you the last day of every month from February 1900 until the middle of the 26th century (on my machine):
;with LastDaysOfMonths as (
select DATEADD(month,
ROW_NUMBER() OVER (ORDER BY so.object_id),
'19000131') as Dt
from sys.objects so,sys.objects so1
)
select * from LastDaysOfMonths
It should be easy enough to use it as part of a larger query or to filter it down to just the dates you want. You can adjust the range of years as needed by changing the constant 19000131. The only important thing to do is make sure that you use a month that has 31 days in it and always have the constant be for day 31.
No need to use a common table expression or anything like that - this simple query will do it:
SELECT DATEADD(d, -1, DATEADD(mm, DATEDIFF(m, 0, DATEADD(m, number, '2013-08-08')) + 1, 0)) AS EndOfMonth
FROM master.dbo.spt_values
WHERE 'P' = type
AND DATEADD(m, number, '2013-08-08') < '2013-11-11';
Although the question is about the last day which #bummi has already answered.
But here is the solution for the first date which might be helpful for someone.
Get the first dates of all the months in-between the #FromDate and #ToDate.
DECLARE #FromDate DATETIME = '2019-08-13'
DECLARE #ToDate DATETIME = '2019-11-25'
;WITH CTE
AS
(
SELECT DATEADD(DAY, -(DAY(#FromDate) - 1), #FromDate) AS FirstDateOfMonth
UNION ALL
SELECT DATEADD(MONTH, 1, FirstDateOfMonth)
FROM CTE
WHERE FirstDateOfMonth < DATEADD(DAY, -(DAY(#ToDate) - 1), #ToDate)
)
SELECT * FROM CTE
Here is the result
--Result
2019-08-01 00:00:00.000
2019-09-01 00:00:00.000
2019-10-01 00:00:00.000
2019-11-01 00:00:00.000

How can I generate Week ending dates (Saturdays) within a date range

I need to generate either a column in a query or a temp table (not sure which one is required)
so that I can have a list of dates that are on Saturday that fall within a given date range.
This list will be used in a join to associate records with weeks.
What are my options?
Sample Input:
From: 03/01/2013
To: 04/30/2013
Results:
Week Ending
- 03/02/2013
- 03/09/2013
- 03/16/2013
- 03/23/2013
- 03/30/2013
- 04/06/2013
- 04/13/2013
- 04/20/2013
- 04/27/2013
- 05/04/2013
Current code:
create table #TBL7(YEAR INT, WEEKNUMBER INT, STARTDATE DATETIME, ENDDATE DATETIME)
begin
declare #startdate datetime
, #enddate datetime
, #ctr int
SET #startdate = CAST(2013 AS VARCHAR)+ '/01/01'
SET #enddate = CAST(2013 AS VARCHAR) + '/12/31'
SET #ctr = 0
WHILE #enddate >= #startdate
BEGIN
SET #ctr = #ctr + 1
INSERT INTO #TBL7
values(year(#startdate), #ctr, #startdate, #startdate + 6)
SET #startdate = #startdate + 7
END
end
select * from #TBL7
First, create a calendar table. Then you have a very simple query:
select [Date]
from dbo.Calendar
where DayOfWeek = 'Saturday' and [Date] between '20130301' and '20130430'
A calendar table is almost always the best approach to working with dates because you're working with data, not code, so you can see it's correct and there's no cryptic code to maintain.
This is Oracle code. Sorry I do not know how to convert this to SQL SERVER. Should not be very hard. All you need is to use proper functions in place of to_date() and to_char(), and calc the difference between start and end date, e.g. (end_date-start_date)+1:
WITH data(r, some_date) AS
(
SELECT 1 r, to_date('03/01/2013', 'MM/DD/YYYY') some_date FROM dual
UNION ALL
SELECT r+1, to_date('03/01/2013', 'MM/DD/YYYY')+r FROM data WHERE r < 61 -- (end_date-start_date)+1
)
SELECT some_date
, To_Char(some_date, 'DY') wk_day
FROM data
WHERE To_Char(some_date, 'DY') = 'SAT'
/
SOME_DATE WK_DAY
--------------------
3/2/2013 SAT
3/9/2013 SAT
3/16/2013 SAT
3/23/2013 SAT
3/30/2013 SAT
4/6/2013 SAT
4/13/2013 SAT
4/20/2013 SAT
4/27/2013 SAT
This should work:
WITH cteWeeks (WeekEnding) As
(
-- Find the Saturday of the first week.
-- Need to allow for different DATEFIRST settings:
SELECT
CASE
WHEN DatePart(dw, DateAdd(day, ##datefirst, #StartDate)) = 7 THEN #StartDate
ELSE DateAdd(day, 7 - DatePart(dw, DateAdd(day, ##datefirst, #StartDate)), #StartDate)
END
UNION ALL
SELECT
DateAdd(day, 7, WeekEnding)
FROM
cteWeeks
WHERE
WeekEnding < #EndDate
)
SELECT
WeekEnding
FROM
cteWeeks
;
http://www.sqlfiddle.com/#!3/d41d8/12095

How to get all the weekend dates of the current year in SQL?

I tried but could not get the right solution. I want an SQL query that lists all the weekend dates of the current year.
I tried this SQL query:
WITH hier(num, lvl) AS (
SELECT 0, 1
UNION ALL
SELECT 100, 1
UNION ALL
SELECT num + 1, lvl + 1
FROM hier
WHERE lvl < 100
)
SELECT lvl [Week],
convert(date,DATEADD(dw, -DATEPART(dw, DATEADD(wk,DATEDIFF(wk,0,'12/31/'+convert(nvarchar,YEAR(getdate()))), 0)+6 ),
DATEADD(wk, DATEDIFF(wk,0,'12/31/'+convert(nvarchar,YEAR(getdate()))), 0)+6 ) - num * 7,101) [End Date]
FROM hier a
where num < 52
ORDER BY [End Date] asc
Its output is like this:
Week End date
52 2012-01-14
51 2012-01-21
50 2012-01-28
49 2012-02-04
I want the dates to start from the beginning – so, the above is missing one weekend, which is 2012-07-01. Also, I want the week numbers to show as 1, 2, 3... instead of 52, 51....
Check out this blog post.
Your question is explained in detail.
DECLARE #Year AS INT,
#FirstDateOfYear DATETIME,
#LastDateOfYear DATETIME
-- You can change #year to any year you desire
SELECT #year = 2010
SELECT #FirstDateOfYear = DATEADD(yyyy, #Year - 1900, 0)
SELECT #LastDateOfYear = DATEADD(yyyy, #Year - 1900 + 1, 0)
-- Creating Query to Prepare Year Data
;WITH cte AS (
SELECT 1 AS DayID,
#FirstDateOfYear AS FromDate,
DATENAME(dw, #FirstDateOfYear) AS Dayname
UNION ALL
SELECT cte.DayID + 1 AS DayID,
DATEADD(d, 1 ,cte.FromDate),
DATENAME(dw, DATEADD(d, 1 ,cte.FromDate)) AS Dayname
FROM cte
WHERE DATEADD(d,1,cte.FromDate) < #LastDateOfYear
)
SELECT FromDate AS Date, Dayname
FROM CTE
WHERE DayName IN ('Saturday','Sunday') -- For Weekend
/*
WHERE DayName LIKE 'Sunday'
WHERE DayName NOT IN ('Saturday','Sunday') -- For Weekday
WHERE DayName LIKE 'Monday' -- For Monday
WHERE DayName LIKE 'Sunday' -- For Sunday
*/
OPTION (MaxRecursion 370)
Will this help
DECLARE #startDate DATETIME, #endDate DATETIME
SELECT #startDate = '2012-01-01', #endDate = '2012-12-31'
;WITH Calender AS (
SELECT #startDate AS dt
UNION ALL
SELECT dt + 1 FROM Calender
WHERE dt + 1 <= #endDate
)
SELECT
dt
,NameMonth = DATENAME(Month, dt)
,NameDay = DATENAME (Weekday,dt)
,WeekofYr = DATEPART(WEEK, dt) FROM Calender
WHERE DATENAME (Weekday,dt) IN ('Sunday')
Option(MaxRecursion 0)
Result(Partial)
dt NameMonth NameDay WeekofYr
2012-01-01 00:00:00.000 January Sunday 1
2012-01-08 00:00:00.000 January Sunday 2
...............................................
...............................................
2012-12-30 00:00:00.000 December Sunday 53
you can try this
DECLARE #FirstDateOfYear DATETIME
SET #FirstDateOfYear = ’2010-01-01′
SELECT DISTINCT DATEADD(d, number, #FirstDateOfYear),
CASE DATEPART(dw, DATEADD(d, number, #FirstDateOfYear))
WHEN 7 THEN ‘Saturday’
WHEN 1 THEN ‘Sunday’
ELSE ‘Work Day’
END
FROM master..spt_values
WHERE number BETWEEN 0 AND 364
AND (DATEPART(dw, DATEADD(d, number, #FirstDateOfYear)) = 1 OR DATEPART(dw, DATEADD(d, number, #FirstDateOfYear)) = 7)
ORDER BY DATEADD(d, number, #FirstDateOfYear)
Try to find the first Saturday by doing this:
Start on 2012-01-01
If it's not a Saturday, add a day
Goto 2
Then, into a temporary table, add that date and the following date (Sunday).
After that, loop the following:
Add 7 and 8 days to the last Saturday you found (you get the following Saturday and Sunday)
Check whether they are still in 2012
If they are, store them in temp table and goto 1
There may be more elegant ways, but that's my quick & dirty solution. As you didn't post any code of what you've tried, I'll leave the implementation up to you.
this also works
declare #dat datetime, #add int
set #dat = '20120101'
set #add = datepart(w,#dat)
set #add = 5 - #add -- friday
set #dat = dateadd(d,#add,#dat)
while #dat <= '20121231'
begin
print #dat
set #dat = dateadd(d,7,#dat)
end
;with AllDaysOfYear (Day) as (
select DATEADD(year,DATEDIFF(year,0,CURRENT_TIMESTAMP),0) --Jan 1st
union all
select DATEADD(day,1,Day) from AllDaysOfYear
where DATEPART(year,DATEADD(day,1,Day)) = DATEPART(year,CURRENT_TIMESTAMP)
)
select
ROW_NUMBER() OVER (ORDER BY Day) as WeekNo,
Day
from
AllDaysOfYear
where
DATEPART(weekday,Day) = DATEPART(weekday,'20120714')
option (maxrecursion 0)
First, generate a set of all of the days in the current year (AllDaysInYear). Then, select those whose weekday is a saturday. The value I've used ('20120714') isn't terribly important - it just has to be any saturday, from any year. I'm just using it to avoid needing to have particular DATEFIRST or language settings.
This query shows how to get the first day of this year and the first day of the next year in the first part. The first day of the next year is calculated once so as not to keep getting and comparing the year parts.
;WITH cte(TheDate,NextYear) AS
(
SELECT CAST(CONVERT(CHAR(4),GETDATE(),112)+'0101' AS DATETIME),
CAST(YEAR(GETDATE())*10000+10101 AS CHAR(8))
UNION ALL
SELECT DateAdd(d,1,TheDate),NextYear
FROM cte
WHERE DateAdd(d,1,TheDate)<NextYear
)
SELECT Week = DatePart(wk,TheDate),
TheDate
FROM cte
WHERE DateName(dw,TheDate) in ('Saturday')
ORDER BY TheDate
OPTION (MAXRECURSION 366)
with t as
(
select 1 b
union all
select 1 b
union all
select 1 b
union all
select 1 b
union all
select 1 b
union all
select 1 b
union all
select 1 b
union all
select 1 b
)
select * from
(
select
current_timestamp
-datepart(dy,current_timestamp)
+row_number() over (order by t.b) d
from t, t t1, t t2
) tmp
where datepart(yyyy,d)=datepart(yyyy,current_timestamp)
and
DATENAME(dw,d)='sunday'
DECLARE #Year AS INT
SELECT #Year = 2020
;WITH weekends AS (
SELECT DATEFROMPARTS(#Year, 1, 1) AS dt
UNION ALL
SELECT DATEADD(DAY, 1, dt)
FROM weekends
WHERE dt < DATEFROMPARTS(#Year, 12, 31)
)
SELECT dt, DATENAME(MONTH, dt), DATENAME(DW, dt)
FROM weekends
WHERE DATEPART(DW, dt) IN (1, 7)
OPTION(MaxRecursion 366)