SQL: get next relative day of week. (Next Monday, Tuesday, Wed.....) - sql

What I need is a date for the next given day (Monday, Tuesday, Wed...) following today's date.
The user is allowed to select what day following they want and that is stored as an int in a table. "Call me next Tuesday (3)"
Sunday = 1
Monday = 2
Tuesday = 3
...
So my table looks like this.
UserID, NextDayID
What I have come up with is:
select dateadd(dd,(7 - datepart(dw,GETDATE()) + NextDayID ) % 7, getdate())
It seems to work and will return today's date if you ask for the next whatever day today is which I can add a week if needed.
What I am wondering is, is that a good solution or is there something that I'm missing?

1) Your solution uses a non-deterministic function: datepart(dw...) . Because of this aspect, changing DATEFIRST setting will gives different results. For example, you should try:
SET DATEFIRST 7;
your solution;
and then
SET DATEFIRST 1;
your solution;
2) Following solution is independent of DATEFIRST/LANGUAGE settings:
DECLARE #NextDayID INT = 0 -- 0=Mon, 1=Tue, 2 = Wed, ..., 5=Sat, 6=Sun
SELECT DATEADD(DAY, (DATEDIFF(DAY, #NextDayID, GETDATE()) / 7) * 7 + 7, #NextDayID) AS NextDay
Result:
NextDay
-----------------------
2013-09-23 00:00:00.000
This solution is based on following property of DATETIME type:
Day 0 = 19000101 = Mon
Day 1 = 19000102 = Tue
Day 2 = 19000103 = Wed
...
Day 5 = 19000106 = Sat
Day 6 = 19000107 = Sun
So, converting INT value 0 to DATETIME gives 19000101.
If you want to find the next Wednesday then you should start from day 2 (19000103/Wed), compute days between day 2 and current day (20130921; 41534 days), divide by 7 (in order to get number of full weeks; 5933 weeks), multiple by 7 (41531 fays; in order to get the number of days - full weeks between the first Wednesday/19000103 and the last Wednesday) and then add 7 days (one week; 41538 days; in order to get following Wednesday). Add this number (41538 days) to the starting date: 19000103.
Note: my current date is 20130921.
Edit #1:
DECLARE #NextDayID INT;
SET #NextDayID = 1; -- Next Sunday
SELECT DATEADD(DAY, (DATEDIFF(DAY, ((#NextDayID + 5) % 7), GETDATE()) / 7) * 7 + 7, ((#NextDayID + 5) % 7)) AS NextDay
Result:
NextDay
-----------------------
2013-09-29 00:00:00.000
Note: my current date is 20130923.

A calendar table is an alternative to using a bunch of date functions and date arithmetic. A minimal calendar table for this particular problem might look something like this.
2013-09-20 Fri
2012-09-21 Sat
2012-09-22 Sun
2012-09-23 Mon
2012-09-24 Tue
...
So a query to get the next Monday might look like this.
select min(cal_date)
from calendar
where cal_date > current_date
and day_of_week = 'Mon';
In practice, you'll probably want a lot more columns in the calendar table, because you'll find a lot of uses for it.
Also, code that uses a calendar table can usually be seen to be obviously correct. Reading the code above is simple: select the minimum calendar date that's after today and that falls on Monday. It's pretty rare to see code that relies on date functions and date arithmetic that's obviously correct.
A calendar table in PostgreSQL

It's an old question. But I'm sure that posting better solution worth it.
-- 0 = 1st Mon, 1 = 1st Tue, 2 = 1st Wed, ..., 5 = 1st Sat, 6 = 1st Sun
-- 7 = 2nd Mon, 8 = 2nd Tue, ...
declare #NextDayID int = 0, #Date date = getdate()
select cast (cast (
-- last Monday before [Date] inclusive, starting from 1900-01-01
datediff (day, #NextDayID % 7, #Date) / 7 * 7
-- shift on required number of days
+ #NextDayID + 7
as datetime) as date)
This solution is improved solution of #Bogdan Sahlean.
It can operate #NextDayID that is greater than 6.
So you can, for example, find 2nd Monday from today.
Following query shows that my solution works correctly.
select [Date]
, convert (char(5), [0], 10) as Mon1
, convert (char(5), [1], 10) as Tue1
, convert (char(5), [2], 10) as Wed1
, convert (char(5), [3], 10) as Thu1
, convert (char(5), [4], 10) as Fri1
, convert (char(5), [5], 10) as Sat1
, convert (char(5), [6], 10) as Sun1
, convert (char(5), [7], 10) as Mon2
, convert (char(5), [8], 10) as Tue2
from (
select [Date], NextDayID
, cast (cast (
datediff (day, NextDayID % 7, [Date]) / 7 * 7 -- last Monday before [Date] inclusive, starting from 1900-01-01
+ NextDayID + 7 -- shift on required number of days
as datetime) as date) as NextDay
from (
select datefromparts (2018, 5, dt) as [Date]
from (values(14),(15),(16),(17),(18),(19),(20))t_(dt)
) d
cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8))nd(NextDayID)
) t
pivot (
min (NextDay) for NextDayID in ([0], [1], [2], [3], [4], [5], [6], [7], [8])
) pvt
Result:
Date | Mon1 | Tue1 | Wed1 | Thu1 | Fri1 | Sat1 | Sun1 | Mon2 | Tue2
-----------+-------+-------+-------+-------+-------+-------+-------+-------+------
2018-05-14 | 05-21 | 05-15 | 05-16 | 05-17 | 05-18 | 05-19 | 05-20 | 05-28 | 05-22
2018-05-15 | 05-21 | 05-22 | 05-16 | 05-17 | 05-18 | 05-19 | 05-20 | 05-28 | 05-29
2018-05-16 | 05-21 | 05-22 | 05-23 | 05-17 | 05-18 | 05-19 | 05-20 | 05-28 | 05-29
2018-05-17 | 05-21 | 05-22 | 05-23 | 05-24 | 05-18 | 05-19 | 05-20 | 05-28 | 05-29
2018-05-18 | 05-21 | 05-22 | 05-23 | 05-24 | 05-25 | 05-19 | 05-20 | 05-28 | 05-29
2018-05-19 | 05-21 | 05-22 | 05-23 | 05-24 | 05-25 | 05-26 | 05-20 | 05-28 | 05-29
2018-05-20 | 05-21 | 05-22 | 05-23 | 05-24 | 05-25 | 05-26 | 05-27 | 05-28 | 05-29
This solution doesn't depend on ##datefirst.

I think this is the best way of doing of finding the next Monday
CONVERT(VARCHAR(11),DateAdd(DAY,case
when (DateName(WEEKDAY, NextVisitDate) ='Tuesday') Then 6
when (DateName(WEEKDAY, NextVisitDate) ='Wednesday') Then 5
when (DateName(WEEKDAY, NextVisitDate) ='Thursday') Then 4
when (DateName(WEEKDAY, NextVisitDate) ='Friday') Then 3
when (DateName(WEEKDAY, NextVisitDate) ='Saturday') Then 2
when (DateName(WEEKDAY, NextVisitDate) ='Sunday') Then 1
else 0 end, DateAdd(DAY, DateDiff(DAY, 0, NextVisitDate), 0)),106) AS Monday,

Find the next upcoming day including today if today is that day which needs to be found out.
Just make a tweak... Set the variable #weekdayno as follows:
1 = Sunday, 2 = Monday, 3 = Tuesday, 4 = Wednesday, 5 = Thursday, 6 = Friday, 7 = Saturday
DECLARE #weekdayno INT
DECLARE #todayno INT
SET #weekdayno = 2 ---For Monday----
SET #todayno = DATEPART(dw,GETDATE())
SELECT CASE
WHEN (#todayno = #weekdayno)
THEN CONVERT(varchar, GETDATE(), 101)
WHEN (#todayno < #weekdayno)
THEN CONVERT(varchar, (#weekdayno - #todayno + GETDATE()), 101)
WHEN (#todayno > #weekdayno)
then CONVERT(varchar,(GETDATE() - (#todayno - #weekdayno) + 7), 101)
END AS UpcomingOrToday

The following function enables to you generate the table on-the-fly...this is how I usually do it...I don't like the idea of a perm date table...seems unnecessary, but every person and situation are different :-)
CREATE function [dbo].[fxDateTable]
(
#begindate datetime = null
, #enddate datetime = null
)
RETURNS #dates TABLE
(
EventDate datetime primary key not null
)
as
begin
select #enddate = isnull(#enddate, getdate())
select #begindate = isnull(#begindate, dateadd(day, -3, #enddate))
insert #dates
select dateadd(day, number, #begindate)
from
(select distinct number from master.dbo.spt_values
where name is null
) n
where dateadd(day, number, #begindate) < #enddate
return
end

Try this: This will give the date for required weekday in a month.
declare #monthstartdate date='2020-01-01',#monthenddate date='2020-01-31',#weekday char(9)='thursday',#weeknum int=4
; with cte(N,WeekDayName_C,Date_C) as
(select 1,datename(WEEKDAY,#monthstartdate),#monthstartdate
union all
select n+1,datename(WEEKDAY,dateadd(day,n,#monthstartdate)),dateadd(day,n,#monthstartdate) from cte where n<31 and Date_C<=#monthenddate )
select * from (select *,ROW_NUMBER() over (partition by WeekDayName_C order by Date_C asc)Weeknum from cte)a
where WeekDayName_C=#weekday and Weeknum=#weeknum

I made this as a function, in which the procedure uses available streamlined knowledge thus it's, I think, a robust solution.
CREATE FUNCTION [nilnul.time_._dated.date].[NextWeekday]
(
#nextWeekDay int -- sunday as firstday is 1.
)
RETURNS datetime
AS
BEGIN
declare #time datetime;
set #time=getdate();
declare #weekday int;
set #weekday = datepart(weekday, #time) ;
declare #diff int;
set #diff= #nextWeekDay-#weekday;
--modulo 7 bijectively
declare #moduloed int;
set #moduloed = case
when #diff <=0 then #diff+7
else #diff
end;
return dateadd(day, #moduloed, #time);
END

I couldn't resist sharing my version. This is primitive for next business/weekday, but just change the "not in ('Saturday','Sunday')" part to be the day you are looking for inside the next week.
select top 1 [date]=convert(date, [date]),
, DayName = datename(dw, [date])
, Offset = [day]
from (
select [0]=getdate()
, [1]=getdate()+1
, [2]=getdate()+2
, [3]=getdate()+3
, [4]=getdate()+4
, [5]=getdate()+5
, [6]=getdate()+6) PVT
unpivot([date] for [day] in ([0],[1],[2],[3],[4],[5],[6])) as unpvt
where datename(dw,[date]) not in ('Saturday','Sunday') --wut day you lookin for?
and getdate() <> [date] --do you want today to be part of the results?
order by [date] asc

Related

How to get week date (7days interval) from SQL Server

I have a table tbl_Customer_Reg and columns are
| ID | Cust_Name | Registration_Date
+------+-----------+------------------
| 1001 | Mr. ABC | 2021-03-13
| 1002 | Mr. MNO | 2021-02-03
| 1003 | Mr. QWE | 2021-04-12
| 1004 | Mr. XYZ | 2021-01-17
Customers are subscribed to a weekly plan. That means every week they get a message and renew every week according to Registration_Date. That means Mr. XYZ renew every week 17,24,31 January 2021 and so on.
Now I want to know the current date (2021-08-20) or before what is the week date of Mr. XYZ.
I think you should create table-function (use cross apply in query) which used cursor or CTE or while.
I write a simple with CTE(maxrecursion 200). You can try this:
CREATE OR ALTER FUNCTION dbo.fnGetWeeklyDateWithDate(#date date)
RETURNS #Result TABLE(WeekDate date, Lev int)
AS
begin
;WITH CTE
AS
(
SELECT #date WeekDate, 1 Lev
UNION ALL
SELECT DATEADD( Week, 1, WeekDate), Lev + 1
FROM CTE c
WHERE DATEADD( Week, 1, WeekDate) <= CAST(GETDATE() as date)
AND Lev < 200
)
INSERT INTO #Result
SELECT WeekDate, Lev
FROM CTE
OPTION (maxrecursion 200)
RETURN
END
result:
A little bit of date arithmetic should do the trick:
SELECT *,
LastRenewal = DATEADD(day, DATEDIFF(day, GETDATE(), Registration_Date) % 7, CAST(GETDATE() AS date)),
NextRenewal = DATEADD(day, DATEDIFF(day, GETDATE(), Registration_Date) % 7 + 7, CAST(GETDATE() AS date))
FROM YourTable;

How to get the Starting date and ending date of weeks using week number in my case using SQL Server?

I already find to get the week number but, that shows the date in different way.
Actually When I check the week number for the Date of
select datepart(wk,'2016-01-02') //Saturday
output: 1
select datepart(wk,'2016-01-03') //Sunday
output: 2
But when I get the date of starting and ending date of weeks using week number, It shows different.
DECLARE #weekStart INT
DECLARE #weekEnd INT
DECLARE #Year INT
set #weekStart = 1
set #Year = 2016
DECLARE #WeekStartDate date
DECLARE #WeekEndDate date
SET #WeekStartDate = convert(date,DATEADD (WEEK, #weekStart, DATEADD (YEAR, #Year-1900, 0)) - 4 -
DATEPART(DW, DATEADD (WEEK, #weekStart, DATEADD (YEAR, #Year-1900, 0)) - 4) + 1)
SET #WeekEndDate =convert(date,DATEADD (WEEK, #weekStart+1, DATEADD (YEAR, #Year-1900, 0)) - 4 -
DATEPART(DW, DATEADD (WEEK, #weekStart+1, DATEADD (YEAR, #Year-1900, 0)) - 4) + 1)
select #WeekStartDate,#WeekEndDate
output:
StartingDate EndingDate
--------------------------
2016-01-03 2016-01-09
I am expecting output is, if I give week = 1 it should give StartingDate = **2016-01-01 and **EndingDate =2016-01-02
for the week number 2, it should give 2016-01-03 2016-01-09
You can get the absolute start/end for the week and then adjust for the current year the first week start and the last week end. You only really need to calculate the start because the end is start + 6 days:
create procedure spWeekDates #year int, #week int
as
declare #firstWeekDay int
declare #yearStart datetime, #weekStartDate datetime, #weekEndDate datetime
set datefirst 7 -- change as needed
set #yearStart=cast(#year as char(4))+'0101' -- years always start on 01/01 [citation needed]
set #firstWeekDay=datepart(weekday,#yearStart)
-- absolute start/end dates
set #weekStartDate=dateadd(week,#week-1,#yearStart)-#firstWeekDay+1
set #weekEndDate=dateadd(day,6,#weekStartDate)
-- adjusting for target year
if year(#weekStartDate)<#year set #weekStartDate=#yearStart
if year(#weekEndDate)>#year set #weekEndDate=cast(#year as char(4))+'1231'
select #weekStartDate as WeekStartDate, #weekEndDate as WeekEndDate
go
exec spWeekDates 2016,1
exec spWeekDates 2016,2
exec spWeekDates 2016,53
go
Results:
| WeekStartDate | WeekEndDate |
|---------------------|---------------------|
| 2016-01-01 00:00:00 | 2016-01-02 00:00:00 |
| WeekStartDate | WeekEndDate |
|---------------------|---------------------|
| 2016-01-03 00:00:00 | 2016-01-09 00:00:00 |
| WeekStartDate | WeekEndDate |
|---------------------|---------------------|
| 2016-12-25 00:00:00 | 2016-12-31 00:00:00 |
You have to get day of the week of first day in year
if it doesn't equals 1 then you have to set #weekStart = #weekStart -1
and set #StartingDate = first day in year

SQL Query to Roll Up Data from the Last 7 Days

Let's assume I have a table structure like this.
CheckIn
- int checkInId pk
- int companyPositionId
- Date checkInDate
Let's say I want to get a count of all check ins for the last 7 days from a given date. What would be the best way to do this? Right now I'm making a query for each of the 7 dates AND the company positions. Currently this is too slow because there could be many companyPositions * 7 days. How can I roll this up into one query?
Would it be easiest to generate the last 7 days dates and construct a long query? Could I then group count by a date range for each of the 7 days?
An ideal result back could look like:
companyPositionId, date1Count, date2Count, date3Count, date4Count, date5Count, date6Count.
Example Data:
checkInId | companyPositionId | checkInDate
1 | 1 | 1970-01-01
2 | 1 | 1970-01-02
3 | 1 | 1970-01-03
4 | 1 | 1970-01-04
5 | 1 | 1970-01-05
6 | 1 | 1970-01-06
7 | 1 | 1970-01-07
8 | 2 | 1970-01-01
9 | 2 | 1970-01-02
10 | 2 | 1970-01-03
11 | 2 | 1970-01-04
12 | 2 | 1970-01-05
13 | 2 | 1970-01-06
14 | 2 | 1970-01-07*
15 | 2 | 1970-01-07*
My current query is this:
SELECT * FROM CheckIn
WHERE (startDate) <= (inputDate)
AND (inputDate) <= (endDate)
AND companyPositionId = (companyPositionId);
I then loop through each startDate/endDate that is generated from the beginning of the day and end of that day. And then each of the companyPositionId's.
Ideal result:
companyPositionId | date1Count | date2Count | date3Count | date4Count | date5Count | date6Count | date7Count
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1
2 | 1 | 1 | 1 | 1 | 1 | 1 | 2
You can do this with the PIVOT command, or with conditional SUMs:
DECLARE #my_date DATE = CAST(GETDATE() AS DATE)
SELECT
companyPositionId,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -7, #my_date) THEN 1 ELSE 0 END) AS date1Count,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -6, #my_date) THEN 1 ELSE 0 END) AS date2Count,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -5, #my_date) THEN 1 ELSE 0 END) AS date3Count,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -4, #my_date) THEN 1 ELSE 0 END) AS date4Count,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -3, #my_date) THEN 1 ELSE 0 END) AS date5Count,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -2, #my_date) THEN 1 ELSE 0 END) AS date6Count,
SUM(CASE WHEN CAST(checkInDate AS DATE) = DATEADD(DAY, -1, #my_date) THEN 1 ELSE 0 END) AS date7Count
FROM
CheckIn
WHERE
checkInDate BETWEEN DATEADD(DAY, -7, GETDATE()) AND DATEADD(DAY, -1, GETDATE())
GROUP BY
companyPositionId
If your checkInDate has a time component then you'll need to account for that.
I declared the #my_date variable just to avoid having to repeat that expression in the query a bunch of times, but you could replace the variable with that expression and it would work as well. You could also use BETWEEN which might have better performance since the optimizer could then potentially use an index on your checkInDate. Just calculate midnight/11:59:59 of each of the days instead of looking for equality.
Look at
Declare #d date= '2016-05-05'; -- parameter, we need this day and six previous
Select
companyPositionId
,date1Count = count(case checkInDate when #d then checkInId end)
,date2Count = count(case checkInDate when dateadd(d,-1,#d) then checkInId end)
--...
from checkIn
where checkInDate between dateadd(d,-6,#d) and #d
group by companyPositionId
order by companyPositionId;
Here's a quick pivot example assuming you're looking for the previous 7 days of the #inputDate. This should work even with the time component since it goes off a DATEDIFF with days only.
DECLARE #InputDate DATE = '1/8/1970'
;WITH CTE AS (
SELECT *, DATEDIFF(DD, checkInDate, #InputDate) AS DaysAgo FROM #CheckIns
)
SELECT
companyPositionId,
SUM([7]) AS date1Count,
SUM([6]) AS date2Count,
SUM([5]) AS date3Count,
SUM([4]) AS date4Count,
SUM([3]) AS date5Count,
SUM([2]) AS date6Count,
SUM([1]) AS date7Count -- Reversed columns since you wanted 7 to be most recent day
FROM CTE
PIVOT (COUNT(checkInId) FOR DaysAgo IN ([1], [2], [3], [4], [5], [6], [7])) PVT
GROUP BY
companyPositionId
This gives the following results matching your desired output:
companyPositionId date1Count date2Count date3Count date4Count date5Count date6Count date7Count
----------------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 2
Create Data:
CREATE TABLE #checkin (
checkInId INT IDENTITY(1, 1),
companyPositionId int,
checkInDate DATE
)
DECLARE #counter INT = 100
WHILE #counter > 0
BEGIN
INSERT INTO #checkin
( companyPositionId, checkInDate )
VALUES ( RAND() * 10 + 1, -- 10 possible companies?
DATEADD(day, RAND()*-7, GETDATE()) -- random days in the last 2 weeks
)
SET #counter = #counter - 1
END
Logic starts here:
DECLARE
#now DATETIME = GETDATE(),
#days INT = -7 -- Our interval of interest
This logic is partially borrowed from Bogdan Sahlean, his results were getting all '1' for me, so I changed the dayNum calculation
SELECT *
FROM (
SELECT companyPositionId, checkInId, 1 + CAST(DATEDIFF(DAY,checkInDate, #now) AS INT) AS DayNum
FROM #CheckIn
WHERE checkInDate BETWEEN CAST(DATEADD(DAY, #days, #now) AS DATE) AND #now
) AS ps -- Pivot source
PIVOT ( COUNT(checkInId) FOR DayNum IN ([1], [2], [3], [4], [5], [6], [7]) ) AS p
DROP TABLE #checkin

Duration overlap causing double counting

I'm using SQL Server Management Studio 2008 for query creation. Reporting Services 2008 for report creation.
I have been trying to work this out over a couple of weeks and I have hit a brick wall. I’m hoping someone will be able to come up with the solution as right now my brain has turned to mush.
I am currently developing an SQL query that will be feeding data through to a Reporting Services report. The aim of the report is to show the percentage of availability for first aid providers within locations around the county we are based in. The idea is that there should be only one first aider providing cover at a time at each of our 20 locations.
This has all been working fine apart from the first aiders at one location have been overlapping their cover at the start and end of each period of cover.
Example of cover overlap:
| Location | start_date | end_date |
+----------+---------------------+---------------------+
| Wick | 22/06/2015 09:00:00 | 22/06/2015 19:00:00 |
| Wick | 22/06/2015 18:30:00 | 23/06/2015 09:00:00 |
| Wick | 23/06/2015 09:00:00 | 23/06/2015 18:30:00 |
| Wick | 23/06/2015 18:00:00 | 24/06/2015 09:00:00 |
+----------+---------------------+---------------------+
In a perfect world the database that they set their cover in wouldn’t allow them to do this but it’s an externally developed database that doesn’t allow us to make changes like that to it. We also aren’t allowed to create functions, stored procedures, tally tables etc…
The query itself should return the number of minutes that each location has had first aid cover for, then broken down into hours of the day. Any overlap in cover shouldn’t end up adding additional cover and should be merged. One person can be on at a time, if they overlap then it should only count as one person lot of cover.
Example Output:
+----------+---------------------+---------------------+----------+--------------+--------+-------+------+----------+
| Location | fromDt | toDt | TimeDiff | Availability | DayN | DayNo | Hour | DayCount |
+----------+---------------------+---------------------+----------+--------------+--------+-------+------+----------+
| WicK | 22/06/2015 18:00:00 | 22/06/2015 18:59:59 | 59 | 100 | Monday | 1 | 18 | 0 |
| WicK | 22/06/2015 18:30:00 | 22/06/2015 18:59:59 | 29 | 50 | Monday | 1 | 18 | 0 |
| WicK | 22/06/2015 19:00:00 | 22/06/2015 19:59:59 | 59 | 100 | Monday | 1 | 19 | 0 |
+----------+---------------------+---------------------+----------+--------------+--------+-------+------+----------+
Example Code:
DECLARE
#StartTime datetime,
#EndTime datetime,
#GivenDate datetime;
SET #GivenDate = '2015-06-22';
SET #StartTime = #GivenDate + ' 00:00:00';
SET #EndTime = '2015-06-23' + ' 23:59:59';
Declare #Sample Table
(
Location Varchar(50),
StartDate Datetime,
EndDate Datetime
)
Insert #Sample
Select
sta.location,
act.Start,
act.END
from emp,
con,
sta,
act
where
emp.ID = con.ID
and con.location = sta.location
and SUBSTRING(sta.ident,3,2) in ('51','22')
and convert(varchar(10),act.start,111) between #GivenDate and #EndTime
and act.ACT= 18
group by sta.location,
act.Start,
act.END
order by 2
;WITH Yak (location, fromDt, toDt, maxDt,hourdiff)
AS (
SELECT location,
StartDate,
/*check if the period of cover rolls onto the next hour */
convert(datetime,convert(varchar(21),
CONVERT(varchar(10),StartDate,111)+' '
+convert(varchar(2),datepart(hour,StartDate))+':59'+':59'))
,
EndDate
,dateadd(hour,1,dateadd(hour, datediff(hour, 0, StartDate), 0))-StartDate
FROM #Sample
UNION ALL
SELECT location,
dateadd(second,1,toDt),
dateadd(hour, 1, toDt),
maxDt,
hourdiff
FROM Yak
WHERE toDt < maxDt
) ,
TAB1 (location, FROMDATE,TODATE1,TODATE) AS
(SELECT
location,
#StartTime,
convert(datetime,convert(varchar(21),
CONVERT(varchar(10),#StartTime,120)+' '
+convert(varchar(2),datepart(hour,#StartTime))+':59'+':59.999')),
#EndTime
from #Sample
UNION ALL
SELECT
location,
(DATEADD(hour, 1,(convert(datetime,convert(varchar(21),
CONVERT(varchar(10),FROMDATE,120)+' '
+convert(varchar(2),datepart(hour,FROMDATE))+':00'+':00.000')))))ToDate,
(DATEADD(hour, 1,(convert(datetime,convert(varchar(21),
CONVERT(varchar(10),TODATE1,120)+' '
+convert(varchar(2),datepart(hour,TODATE1))+':59'+':59.999'))))) Todate1,
TODATE
FROM TAB1 WHERE TODATE1 < TODATE
),
/*CTE Tab2 adds zero values to all possible hours between start and end dates */
TAB2 AS
(SELECT location, FROMDATE,
CASE WHEN TODATE1 > TODATE THEN TODATE ELSE TODATE1 END AS TODATE
FROM TAB1)
SELECT location,
fromDt,
/* Display MaxDT as start time if cover period goes into next dat */
CASE WHEN toDt > maxDt THEN maxDt ELSE toDt END AS toDt,
/* If the end date is on the next day find out the minutes between the start date and the end of the day or find out the minutes between the next day and the end date */
Case When ToDt > Maxdt then datediff(mi,fromDt,maxDt) else datediff(mi,FromDt,ToDt) end as TimeDiff,
Case When ToDt > Maxdt then round(datediff(S,fromDt,maxDt)/3600.0*100,0) else round(datediff(S,FromDt,ToDt)/3600.0*100.0,0) end as Availability,
/*Display the name of the day of the week*/
CASE WHEN toDt > maxDt THEN datename(dw,maxDt) ELSE datename(dw,fromDt) END AS DayN,
CASE WHEN toDt > maxDt THEN case when datepart(dw,maxDt)-1 = 0 then 7 else datepart(dw,maxDt)-1 end ELSE case when datepart(dw,fromDt)-1 = 0 then 7 else datepart(dw,fromDt)-1 END end AS DayNo
,DATEPART(hour, fromDt) as Hour,
'0' as DayCount
FROM Yak
where Case When ToDt > Maxdt then datediff(mi,fromDt,maxDt) else datediff(mi,FromDt,ToDt) end <> 0
group by location,fromDt,maxDt,toDt
Union all
SELECT
tab2.location,
convert(varchar(19),Tab2.FROMDATE,120),
convert(varchar(19),Tab2.TODATE,120),
'0',
'0',
datename(dw,FromDate) DayN,
case when datepart(dw,FromDate)-1 = 0 then 7 else datepart(dw,FromDate)-1 end AS DayNo,
DATEPART(hour, fromDate) as Hour,
COUNT(distinct datename(dw,fromDate))
FROM TAB2
Where datediff(MINUTE,convert(varchar(19),Tab2.FROMDATE,120),convert(varchar(19),Tab2.TODATE,120)) > 0
group by location, TODATE, FROMDATE
Order by 2
option (maxrecursion 0)
I have tried the following forum entries but they haven't worked in my case:
http://forums.teradata.com/forum/general/need-help-merging-consecutive-and-overlapping-date-spans
Checking for time range overlap, the watchman problem [SQL]
Calculate Actual Downtime ignoring overlap in dates/times
Sorry for being so lengthy but I thought I would try to give you as much detail as possible. Any help will be really appreciated. Thank you.
So the solution I came up with uses temp tables, which you can easily change to be CTEs so you can avoid using a stored procedure.
I tried working with window functions to find overlapping records and get the min and max times, the issue is where you have overlap chaining e.g. 09:00 - 09:10, 09:05 - 09:15, 09:11 - 09:20, so all minutes from 09:00 to 09:20 are covered, but it's almost impossible to tell that 09:00 - 09:10 is related to 09:11 - 09:20 without recursing through the results until you get to the bottom of the chain. (Hopefully that makes sense).
So I exploded out all of the date ranges into every minute between the StartDate and EndDate, then you can use the ROW_NUMBER() window function to catch any duplicates, which in turn you can use to see how many different people covered the same minute.
CREATE TABLE dbo.dates
(
Location VARCHAR(64),
StartDate DATETIME,
EndDate DATETIME
);
INSERT INTO dbo.dates VALUES
('Wick','20150622 09:00:00','20150622 19:00:00'),
('Wick','20150622 18:30:00','20150624 09:00:00'),
('Wick','20150623 09:00:00','20150623 18:30:00'),
('Wick','20150623 18:00:00','20150624 09:00:00'),
('Wick','20150630 09:00:00','20150630 09:30:00'),
('Wick','20150630 09:00:00','20150630 09:45:00'),
('Wick','20150630 09:10:00','20150630 09:25:00'),
('Wick','20150630 09:35:00','20150630 09:55:00'),
('Wick','20150630 09:57:00','20150630 10:10:00');
SELECT ROW_NUMBER() OVER (PARTITION BY Location ORDER BY StartDate) [Id],
Location,
StartDate,
EndDate
INTO dbo.overlaps
FROM dbo.dates;
SELECT TOP 10000 N=IDENTITY(INT, 1, 1)
INTO dbo.Num
FROM master.dbo.syscolumns a CROSS JOIN master.dbo.syscolumns b;
SELECT 0 [N] INTO dbo.Numbers;
INSERT INTO dbo.Numbers SELECT * FROM dbo.Num;
SELECT [Location] = raw.Location,
[WorkedDate] = CAST([MinuteWorked] AS DATE),
[DayN] = DATENAME(WEEKDAY, [MinuteWorked]),
[DayNo] = DATEPART(WEEKDAY, [MinuteWorked]) -1,
[Hour] = DATEPART(HOUR, [MinuteWorked]),
[MinutesWorked] = SUM(IIF(raw.[Minutes] = 1, 1, 0)),
[MaxWorkers] = MAX(raw.[Minutes])
FROM
(
SELECT
o.Location,
DATEADD(MINUTE, n.N, StartDate) [MinuteWorked],
ROW_NUMBER() OVER (PARTITION BY o.Location, DATEADD(MINUTE, n.N, StartDate) ORDER BY DATEADD(MINUTE, n.N, StartDate)) [Minutes]
FROM dbo.overlaps o
INNER JOIN dbo.Numbers n ON n.N < DATEDIFF(MINUTE, StartDate, EndDate)
) raw
GROUP BY
raw.Location,
CAST([MinuteWorked] AS DATE),
DATENAME(WEEKDAY, [MinuteWorked]),
DATEPART(WEEKDAY, [MinuteWorked]) - 1,
DATEPART(HOUR, [MinuteWorked])
Here's a subset of the results:
Location WorkedDate DayN DayNo Hour MinutesWorked MaxWorkers
Wick 2015-06-24 Wednesday 3 8 60 2
Wick 2015-06-30 Tuesday 2 9 58 3
Wick 2015-06-30 Tuesday 2 10 10 1
Here's the fiddle

Get the week start date and week end date from week number

I have a query that counts member's wedding dates in the database.
SELECT
SUM(NumberOfBrides) AS [Wedding Count]
, DATEPART( wk, WeddingDate) AS [Week Number]
, DATEPART( year, WeddingDate) AS [Year]
FROM MemberWeddingDates
GROUP BY DATEPART(year, WeddingDate), DATEPART(wk, WeddingDate)
ORDER BY SUM(NumberOfBrides) DESC
How do I work out when the start and end of each week represented in the result set?
SELECT
SUM(NumberOfBrides) AS [Wedding Count]
, DATEPART(wk, WeddingDate) AS [Week Number]
, DATEPART(year, WeddingDate) AS [Year]
, ??? AS WeekStart
, ??? AS WeekEnd
FROM MemberWeddingDates
GROUP BY DATEPART(year, WeddingDate), DATEPART(wk, WeddingDate)
ORDER BY SUM(NumberOfBrides) DESC
You can find the day of week and do a date add on days to get the start and end dates..
DATEADD(dd, -(DATEPART(dw, WeddingDate)-1), WeddingDate) [WeekStart]
DATEADD(dd, 7-(DATEPART(dw, WeddingDate)), WeddingDate) [WeekEnd]
You probably also want to look at stripping off the time from the date as well though.
Here is a DATEFIRST agnostic solution:
SET DATEFIRST 4 /* or use any other weird value to test it */
DECLARE #d DATETIME
SET #d = GETDATE()
SELECT
#d ThatDate,
DATEADD(dd, 0 - (##DATEFIRST + 5 + DATEPART(dw, #d)) % 7, #d) Monday,
DATEADD(dd, 6 - (##DATEFIRST + 5 + DATEPART(dw, #d)) % 7, #d) Sunday
you can also use this:
SELECT DATEADD(day, DATEDIFF(day, 0, WeddingDate) /7*7, 0) AS weekstart,
DATEADD(day, DATEDIFF(day, 6, WeddingDate-1) /7*7 + 7, 6) AS WeekEnd
Here is another version. If your Scenario requires Saturday to be 1st day of Week and Friday to be last day of Week, the below code will handle that:
DECLARE #myDate DATE = GETDATE()
SELECT #myDate,
DATENAME(WEEKDAY,#myDate),
DATEADD(DD,-(CHOOSE(DATEPART(dw, #myDate), 1,2,3,4,5,6,0)),#myDate) AS WeekStartDate,
DATEADD(DD,7-CHOOSE(DATEPART(dw, #myDate), 2,3,4,5,6,7,1),#myDate) AS WeekEndDate
Expanding on #Tomalak's answer. The formula works for days other than Sunday and Monday but you need to use different values for where the 5 is. A way to arrive at the value you need is
Value Needed = 7 - (Value From Date First Documentation for Desired Day Of Week) - 1
here is a link to the document: https://msdn.microsoft.com/en-us/library/ms181598.aspx
And here is a table that lays it out for you.
| DATEFIRST VALUE | Formula Value | 7 - DATEFIRSTVALUE - 1
Monday | 1 | 5 | 7 - 1- 1 = 5
Tuesday | 2 | 4 | 7 - 2 - 1 = 4
Wednesday | 3 | 3 | 7 - 3 - 1 = 3
Thursday | 4 | 2 | 7 - 4 - 1 = 2
Friday | 5 | 1 | 7 - 5 - 1 = 1
Saturday | 6 | 0 | 7 - 6 - 1 = 0
Sunday | 7 | -1 | 7 - 7 - 1 = -1
But you don't have to remember that table and just the formula, and actually you could use a slightly different one too the main need is to use a value that will make the remainder the correct number of days.
Here is a working example:
DECLARE #MondayDateFirstValue INT = 1
DECLARE #FridayDateFirstValue INT = 5
DECLARE #TestDate DATE = GETDATE()
SET #MondayDateFirstValue = 7 - #MondayDateFirstValue - 1
SET #FridayDateFirstValue = 7 - #FridayDateFirstValue - 1
SET DATEFIRST 6 -- notice this is saturday
SELECT
DATEADD(DAY, 0 - (##DATEFIRST + #MondayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as MondayStartOfWeek
,DATEADD(DAY, 6 - (##DATEFIRST + #MondayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as MondayEndOfWeek
,DATEADD(DAY, 0 - (##DATEFIRST + #FridayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as FridayStartOfWeek
,DATEADD(DAY, 6 - (##DATEFIRST + #FridayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as FridayEndOfWeek
SET DATEFIRST 2 --notice this is tuesday
SELECT
DATEADD(DAY, 0 - (##DATEFIRST + #MondayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as MondayStartOfWeek
,DATEADD(DAY, 6 - (##DATEFIRST + #MondayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as MondayEndOfWeek
,DATEADD(DAY, 0 - (##DATEFIRST + #FridayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as FridayStartOfWeek
,DATEADD(DAY, 6 - (##DATEFIRST + #FridayDateFirstValue + DATEPART(dw,#TestDate)) % 7, #TestDate) as FridayEndOfWeek
This method would be agnostic of the DATEFIRST Setting which is what I needed as I am building out a date dimension with multiple week methods included.
If sunday is considered as week start day, then here is the code
Declare #currentdate date = '18 Jun 2020'
select DATEADD(D, -(DATEPART(WEEKDAY, #currentdate) - 1), #currentdate)
select DATEADD(D, (7 - DATEPART(WEEKDAY, #currentdate)), #currentdate)
Below query will give data between start and end of current week
starting from sunday to saturday
SELECT DOB FROM PROFILE_INFO WHERE DAY(DOB) BETWEEN
DAY( CURRENT_DATE() - (SELECT DAYOFWEEK(CURRENT_DATE())-1))
AND
DAY((CURRENT_DATE()+(7 - (SELECT DAYOFWEEK(CURRENT_DATE())) ) ))
AND
MONTH(DOB)=MONTH(CURRENT_DATE())
Let us break the problem down to two parts:
1) Determine the day of week
The DATEPART(dw, ...) returns a number, 1...7, relative to DATEFIRST setting (docs). The following table summarizes the possible values:
##DATEFIRST
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | DOW |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
| DATEPART(dw, /*Mon*/ '20010101') | 1 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| DATEPART(dw, /*Tue*/ '20010102') | 2 | 1 | 7 | 6 | 5 | 4 | 3 | 2 |
| DATEPART(dw, /*Wed*/ '20010103') | 3 | 2 | 1 | 7 | 6 | 5 | 4 | 3 |
| DATEPART(dw, /*Thu*/ '20010104') | 4 | 3 | 2 | 1 | 7 | 6 | 5 | 4 |
| DATEPART(dw, /*Fri*/ '20010105') | 5 | 4 | 3 | 2 | 1 | 7 | 6 | 5 |
| DATEPART(dw, /*Sat*/ '20010106') | 6 | 5 | 4 | 3 | 2 | 1 | 7 | 6 |
| DATEPART(dw, /*Sun*/ '20010107') | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 7 |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
The last column contains the ideal day-of-week value for Monday to Sunday weeks*. By just looking at the chart we come up with the following equation:
(##DATEFIRST + DATEPART(dw, SomeDate) - 1 - 1) % 7 + 1
2) Calculate the Monday and Sunday for given date
This is trivial thanks to the day-of-week value. Here is an example:
WITH TestData(SomeDate) AS (
SELECT CAST('20001225' AS DATETIME) UNION ALL
SELECT CAST('20001226' AS DATETIME) UNION ALL
SELECT CAST('20001227' AS DATETIME) UNION ALL
SELECT CAST('20001228' AS DATETIME) UNION ALL
SELECT CAST('20001229' AS DATETIME) UNION ALL
SELECT CAST('20001230' AS DATETIME) UNION ALL
SELECT CAST('20001231' AS DATETIME) UNION ALL
SELECT CAST('20010101' AS DATETIME) UNION ALL
SELECT CAST('20010102' AS DATETIME) UNION ALL
SELECT CAST('20010103' AS DATETIME) UNION ALL
SELECT CAST('20010104' AS DATETIME) UNION ALL
SELECT CAST('20010105' AS DATETIME) UNION ALL
SELECT CAST('20010106' AS DATETIME) UNION ALL
SELECT CAST('20010107' AS DATETIME) UNION ALL
SELECT CAST('20010108' AS DATETIME) UNION ALL
SELECT CAST('20010109' AS DATETIME) UNION ALL
SELECT CAST('20010110' AS DATETIME) UNION ALL
SELECT CAST('20010111' AS DATETIME) UNION ALL
SELECT CAST('20010112' AS DATETIME) UNION ALL
SELECT CAST('20010113' AS DATETIME) UNION ALL
SELECT CAST('20010114' AS DATETIME)
), TestDataPlusDOW AS (
SELECT SomeDate, (##DATEFIRST + DATEPART(dw, SomeDate) - 1 - 1) % 7 + 1 AS DOW
FROM TestData
)
SELECT
FORMAT(SomeDate, 'ddd yyyy-MM-dd') AS SomeDate,
FORMAT(DATEADD(dd, -DOW + 1, SomeDate), 'ddd yyyy-MM-dd') AS [Monday],
FORMAT(DATEADD(dd, -DOW + 1 + 6, SomeDate), 'ddd yyyy-MM-dd') AS [Sunday]
FROM TestDataPlusDOW
Output:
+------------------+------------------+------------------+
| SomeDate | Monday | Sunday |
+------------------+------------------+------------------+
| Mon 2000-12-25 | Mon 2000-12-25 | Sun 2000-12-31 |
| Tue 2000-12-26 | Mon 2000-12-25 | Sun 2000-12-31 |
| Wed 2000-12-27 | Mon 2000-12-25 | Sun 2000-12-31 |
| Thu 2000-12-28 | Mon 2000-12-25 | Sun 2000-12-31 |
| Fri 2000-12-29 | Mon 2000-12-25 | Sun 2000-12-31 |
| Sat 2000-12-30 | Mon 2000-12-25 | Sun 2000-12-31 |
| Sun 2000-12-31 | Mon 2000-12-25 | Sun 2000-12-31 |
| Mon 2001-01-01 | Mon 2001-01-01 | Sun 2001-01-07 |
| Tue 2001-01-02 | Mon 2001-01-01 | Sun 2001-01-07 |
| Wed 2001-01-03 | Mon 2001-01-01 | Sun 2001-01-07 |
| Thu 2001-01-04 | Mon 2001-01-01 | Sun 2001-01-07 |
| Fri 2001-01-05 | Mon 2001-01-01 | Sun 2001-01-07 |
| Sat 2001-01-06 | Mon 2001-01-01 | Sun 2001-01-07 |
| Sun 2001-01-07 | Mon 2001-01-01 | Sun 2001-01-07 |
| Mon 2001-01-08 | Mon 2001-01-08 | Sun 2001-01-14 |
| Tue 2001-01-09 | Mon 2001-01-08 | Sun 2001-01-14 |
| Wed 2001-01-10 | Mon 2001-01-08 | Sun 2001-01-14 |
| Thu 2001-01-11 | Mon 2001-01-08 | Sun 2001-01-14 |
| Fri 2001-01-12 | Mon 2001-01-08 | Sun 2001-01-14 |
| Sat 2001-01-13 | Mon 2001-01-08 | Sun 2001-01-14 |
| Sun 2001-01-14 | Mon 2001-01-08 | Sun 2001-01-14 |
+------------------+------------------+------------------+
* For Sunday to Saturday weeks you need to adjust the equation just a little, like add 1 somewhere.
I just encounter a similar case with this one, but the solution here seems not helping me.
So I try to figure it out by myself. I work out the week start date only, week end date should be of similar logic.
Select
Sum(NumberOfBrides) As [Wedding Count],
DATEPART( wk, WeddingDate) as [Week Number],
DATEPART( year, WeddingDate) as [Year],
DATEADD(DAY, 1 - DATEPART(WEEKDAY, dateadd(wk, DATEPART( wk, WeddingDate)-1, DATEADD(yy,DATEPART( year, WeddingDate)-1900,0))), dateadd(wk, DATEPART( wk, WeddingDate)-1, DATEADD(yy,DATEPART( year, WeddingDate)-1900,0))) as [Week Start]
FROM MemberWeddingDates
Group By DATEPART( year, WeddingDate), DATEPART( wk, WeddingDate)
Order By Sum(NumberOfBrides) Desc
The most voted answer works fine except for the 1st week and last week of a year. For example, if the value of WeddingDate is '2016-01-01', the result will be 2015-12-27 and 2016-01-02, but the right answer is 2016-01-01 and 2016-01-02.
Try this:
Select
Sum(NumberOfBrides) As [Wedding Count],
DATEPART( wk, WeddingDate) as [Week Number],
DATEPART( year, WeddingDate) as [Year],
MAX(CASE WHEN DATEPART(WEEK, WeddingDate) = 1 THEN CAST(DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0) AS date) ELSE DATEADD(DAY, 7 * DATEPART(WEEK, WeddingDate), DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0))) END) as WeekStart,
MAX(CASE WHEN DATEPART(WEEK, WeddingDate) = DATEPART(WEEK, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate) + 1, 0))) THEN DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate) + 1, 0)) ELSE DATEADD(DAY, 7 * DATEPART(WEEK, WeddingDate) + 6, DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0))) END) as WeekEnd
FROM MemberWeddingDates
Group By DATEPART( year, WeddingDate), DATEPART( wk, WeddingDate)
Order By Sum(NumberOfBrides) Desc;
The result looks like:
It works for all weeks, 1st or others.
Week Start & End Date From Date For Power BI Dax Formula
WeekStartDate = [DateColumn] - (WEEKDAY([DateColumn])-1)
WeekEndDate = [DateColumn] + (7-WEEKDAY([DateColumn]))
This is my solution
SET DATEFIRST 1; /* change to use a different datefirst */
DECLARE #date DATETIME
SET #date = CAST('2/6/2019' as date)
SELECT DATEADD(dd,0 - (DATEPART(dw, #date) - 1) ,#date) [dateFrom],
DATEADD(dd,6 - (DATEPART(dw, #date) - 1) ,#date) [dateTo]
Get Start Date & End Date by Custom Date
DECLARE #Date NVARCHAR(50)='05/19/2019'
SELECT
DATEADD(DAY,CASE WHEN DATEPART(WEEKDAY, #Date)=1 THEN -6 ELSE 2 - DATEPART(WEEKDAY, #Date) END, CAST(#Date AS DATE)) [Week_Start_Date]
,DATEADD(DAY,CASE WHEN DATEPART(WEEKDAY, #Date)=1 THEN 0 ELSE 8 - DATEPART(WEEKDAY, #Date) END, CAST(#Date AS DATE)) [Week_End_Date]
Another way to do it:
declare #week_number int = 6280 -- 2020-05-07
declare #start_weekday int = 0 -- Monday
declare #end_weekday int = 6 -- next Sunday
select
dateadd(week, #week_number, #start_weekday),
dateadd(week, #week_number, #end_weekday)
Explanation:
#week_number is the week number since the initial calendar date '1900-01-01'. It can be computed this way: select datediff(week, 0, #wedding_date) as week_number
#start_weekday for the week first day: 0 for Monday, -1 if Sunday
#end_weekday for the week last day: 6 for next Sunday, 5 if Saturday
dateadd(week, #week_number, #end_weekday): adds the given number of weeks and the given number of days into the initial calendar date '1900-01-01'
This doesn't come from me, but it got the job done regardless:
SELECT DATEADD(wk, -1, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day previous week
SELECT DATEADD(wk, 0, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day current week
SELECT DATEADD(wk, 1, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day next week
SELECT DATEADD(wk, 0, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day previous week
SELECT DATEADD(wk, 1, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day current week
SELECT DATEADD(wk, 2, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day next week
I found it here.
I have a way other, It is select day Start and day End of Week Current:
DATEADD(d, -(DATEPART(dw, GETDATE()-2)), GETDATE()) is date time Start
and
DATEADD(day,7-(DATEPART(dw,GETDATE()-1)),GETDATE()) is date time End
Not sure how useful this is, but I ended up here from looking for a solution on Netezza SQL and couldn't find one on stack overflow.
For IBM netezza you would use something (for week start mon, week end sun) like:
select
next_day (WeddingDate, 'SUN') -6 as WeekStart,
next_day (WeddingDate, 'SUN') as WeekEnd
for Access Queries, you can use in the below format as a field
"FirstDayofWeek:IIf(IsDate([ForwardedForActionDate]),CDate(Format([ForwardedForActionDate],"dd/mm/yyyy"))-(Weekday([ForwardedForActionDate])-1))"
direct Calculation allowed..