Date Variable for last working day in UK? - sql

Working on UK based project.
I put a lovely variable in to give me a start date and end date of the last working day for a Monday to Friday . Unfortuantely I wanted the start date time to be the start of the day and the end date to be the end of the day . What change can I make to make this happen ?
SET #Startdate =
( CASE
WHEN DATEPART(WEEKDAY, #Startdate) = 7
THEN DATEADD(DAY, -2, #Startdate)
WHEN DATEPART(WEEKDAY, #Startdate) = 1
THEN DATEADD(DAY, (-2 - DATEPART(WEEKDAY, #Startdate)), #Startdate)
ELSE
DATEADD(DAY, -1, #Startdate)
END )
SET #Enddate =
CASE
WHEN DATEPART(WEEKDAY, #Enddate) = 7
THEN DATEADD(DAY, -2, #Enddate)
WHEN DATEPART(WEEKDAY, #Enddate) = 1
THEN DATEADD(DAY, (-2 - DATEPART(WEEKDAY, #Enddate)), #Enddate)
ELSE
DATEADD(DAY, -1, #Enddate)
END
print #Startdate
print #Enddate
Results :
Feb 26 2013 12:00AM
Feb 26 2013 12:00AM
I need Feb 26 2013 00:00 until Feb 27 2013 00:00, so it covers all day Tuesday (the last working day if run today).

This is a solved problem if you perform a cursory Google search (lots of good UDFs for this), but to use your code as is, just add one to the #Enddate calculation if you really do want 26th 0:00 to 27th 0:00 (or add just below 1 like Kenneth Fisher suggests if you want 23:59, which seems better).

Actually 12:00AM is 00:00, you would just need to convert it in another format if you want (http://msdn.microsoft.com/en-us/library/ms187928.aspx).
Just add one day to Feb 26 12:00AM and you'll get Feb 27 12:00AM which is Feb 27 00:00.

Related

Getting “before two days” date sql server

I want to get two days before from current date and that date should not be Saturday and Sunday today is 1st July 2021 so i need to get data for 30th jun 2021 and 29th jun 2021 and that day should not be Saturday and Sunday.
Use a CASE expression:
SELECT CASE DATEPART(dw, GETDATE())
WHEN 2 THEN DATEADD(day, -3, GETDATE()) -- Monday becomes Friday
WHEN 3 THEN DATEADD(day, -4, GETDATE()) -- Tuesday becomes Friday
ELSE DATEADD(day, -2, GETDATE()) -- otherwise roll back 2 days
END;
The above answer assumes that server settings place Sunday as day 1, Monday as day 2, ..., and Saturday as day 7. Without this assumption my answer might be worthless.

SQL Server - Get calander month begining and end

I've tried searching but cannot find anything.
I am trying to get the first and last date of the calander month.
So for example the calander month for January 2020 actually starts on December 30th 2019 and ends on February 2nd 2020. (Week 1 - 5)
|---------------------|-------------------|-------------------|
| Week number | From Date | To Date |
|---------------------|-------------------|-------------------|
| Week 01 | December 30, 2019 | January 5, 2020 |
|---------------------|-------------------|-------------------|
| Week 05 | January 27, 2020 | February 2, 2020 |
|---------------------|-------------------|-------------------|
Using this website to get week numbers
Is this possible?
Many thanks.
If you are using MSSQL-2012 or onwards.
DECLARE #DATE DATETIME='29-JAN-2020'
SELECT DATEADD(DAY, 2 - CASE WHEN DATEPART(WEEKDAY, #DATE-DAY(#DATE)+1)=1 THEN 8 ELSE DATEPART(WEEKDAY, #DATE-DAY(#DATE)+1) END, CAST( #DATE-DAY(#DATE)+1 AS DATE)) [MONTH_START_DATE],
DATEADD(DAY, 8 - CASE WHEN DATEPART(WEEKDAY, EOMONTH(#DATE))=1 THEN 8 ELSE DATEPART(WEEKDAY, EOMONTH(#DATE)) END , CAST(EOMONTH(#DATE) AS DATE)) [MONTH_END_DATE];
You can try on below link:-
https://dbfiddle.uk/?rdbms=sqlserver_2012&fiddle=9747ea25d0d0bc343be8dbcc90803303
You can use this logic:
select convert(date, dateadd(day, 1 - day(getdate()), getdate())) as month_first,
dateadd(day, 1, eomonth(getdate(), -1)) as alternative_month_first,
eomonth(getdate()) as month_last
Of course, you would use whatever date you wanted instead of getdate().

I need data from Prior Monday to saturday when i run my interface on Tuesday at 1:30am. utlized a example query

select *
from VP_TIMESHTPUNCHV42
where (EVENTDATE>=getdate()-8) AND (EVENTDATE <=getdate()-3)
AND PERSONNUM = '668795'
so it should -9 or -8 here? please help me understand about the dates and what dates will be included here ?
If my Tuesday is 15th Oct and the previous Sat is 12thoct and mon is 7thoct
I need data from Mon7th oct to sat12th oct
if you want to get data from Monday to Saturday. WeekDay is from 2(Monday) to 7(Saturday)
select *
from VP_TIMESHTPUNCHV42
where datepart(weekday, EVENTDATE) between 2 and 7 AND PERSONNUM = '668795'
or (if only within this week)
select *
from VP_TIMESHTPUNCHV42
where EVENTDATE between getdate() - 1 and getdate() + 5 AND PERSONNUM = '668795'
select *
from VP_TIMESHTPUNCHV42
where EVENTDATE between dateadd(day, -1, cast(getdate() as date)) and dateadd(day, 5, cast(getdate() as date))
and PERSONNUM = '668795'

Find first date of previous week in SQL Server

I have some dates and week numbers and first day of week is 5 (Friday) in SQL Server. Now I want to calculate previous week and week start date from this below query.
DECLARE #LocationID tinyint = 1,
#FromDate date = '2016-05-20',
#ToDate date = '2016-05-29';
--Step1: ==================================================================
--SET first day of the week of the year
DECLARE #CurrentDayOfWeek INT
SET DATEFIRST 1 -- normalize current dkoray of week to Monday
SET #CurrentDayOfWeek = DATEPART(DW, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0))
SET DATEFIRST #CurrentDayOfWeek -- first day of week is now 5 (Friday)
--SELECT #CurrentDayOfWeek
-----Get Weekend number--------------
DECLARE #WeekStart int, #WeekEnd int
SET #WeekStart=(SELECT { fn WEEK( #FromDate) })
SET #WeekEnd=(SELECT { fn WEEK( #ToDate) })
;WITH AllDate AS
(
SELECT #FromDate as TheDate
UNION ALL
SELECT DATEADD(DAY, 1, TheDate)
FROM AllDate
WHERE DATEADD(DAY, 1, TheDate) <= #ToDate
),
AllDateDetail AS
(
SELECT TheDate,
DATEPART(WEEK, TheDate) AS WeekNumber,
YEAR(TheDate) AS [Year],
UPPER(CONVERT(NVARCHAR(3),DATENAME(WEEKDAY, TheDate))) AS [DayName]
FROM AllDate
)
SELECT
*
, CONVERT(DATE,DATEADD(WK, DATEDIFF(WK, 0, TheDate), 0)) AS LastWeekStart
, { fn WEEK( CONVERT(DATE,DATEADD(WK, DATEDIFF(WK, 0, TheDate) - 1, 0))) } AS WeekNumber
FROM AllDateDetail
--Select dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) as LastWeekStart
--Select dateadd(wk, datediff(wk, 0, getdate()), 0) as ThisWeekStart
--Select dateadd(wk, datediff(wk, 0, getdate()) + 1, 0) as NextWeekStart
The current result of this query:
Expected result:
TheDate WeekNumber [Year] [DayName] LastWeekStart LastWeekNumber
20-05-2016 21 2016 FRI 13-05-2016 20
21-05-2016 21 2016 SAT 13-05-2016 20
22-05-2016 21 2016 SUN 13-05-2016 20
23-05-2016 21 2016 MON 13-05-2016 20
24-05-2016 21 2016 TUE 13-05-2016 20
25-05-2016 21 2016 WED 13-05-2016 20
26-05-2016 21 2016 THU 13-05-2016 20
27-05-2016 22 2016 FRI 20-05-2016 21
28-05-2016 22 2016 SAT 20-05-2016 21
29-05-2016 22 2016 SUN 20-05-2016 21
Can you help me? Thanks
Here's some handy ways of calculating First/Last day of This/Last week respecting DATEFIRST that I blogged a couple of weeks ago.
SET DATEFIRST 5 --Friday
-- Start/End of Weeks respecting DATEFIRST
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'First Day of Current Week (DATEFIRST)';
SELECT DATEADD(DAY, 7-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'Last Day of Current Week (DATEFIRST)';
SELECT DATEADD(DAY, -6-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'First Day of Last Week (DATEFIRST)';
SELECT DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'Last Day of Last Week (DATEFIRST)';
(Gratuitous blog promo https://www.rednotebluenote.com/2016/04/first-day-of-the-week-and-datefirst/ )

MSSQL - Getting last 6 weeks returns last 8 weeks

I am having a problem with week numbers. The customers week starts on a Tuesday, so ends on a Monday. So I have done:
Set DateFirst 2
When I then use
DateAdd(ww,#WeeksToShow, Date)
It occasionally gives me 8 weeks of information. I think it is because it goes over to the previous year, but I am not sure how to fix it.
If I do:
(DatePart(dy,Date) / 7) - #WeeksToShow
Then it works better, but obviously doesn't work going through to previous years as it just goes to minus figures.
Edit:
My currently SQL (If it helps at all without any data)
Set DateFirst 2
Select
DATEPART(yyyy,SessionDate) as YearNo,
DATEPART(ww,SessionDate) as WeekNo,
DATEADD(DAY, 1 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate +SessionTime AS DATE)) [WeekStart],
DATEADD(DAY, 7 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate + SessionTime AS DATE)) [WeekEnd],
DateName(dw,DATEADD(DAY, 7 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate + SessionTime AS DATE))) as WeekEndName,
Case when #ConsolidateSites = 1 then 0 else SiteNo end as SiteNo,
Case when #ConsolidateSites = 1 then 'All' else CfgSites.Name end as SiteName,
GroupNo,
GroupName,
DeptNo,
DeptName,
SDeptNo,
SDeptName,
PluNo,
PluDescription,
SUM(Qty) as SalesQty,
SUM(Value) as SalesValue
From
PluSalesExtended
Left Join
CfgSites on PluSalesExtended.SiteNo = CfgSites.No
Where
Exists (Select Descendant from DescendantSites where Parent in (#SiteNo) and Descendant = PluSalesExtended.SiteNo)
AND (DATEPART(WW,SessionDate + SessionTime) !=DATEPART(WW,GETDATE()))
AND SessionDate + SessionTime between DATEADD(ww,#NumberOfWeeks * -1,#StartingDate) and #StartingDate
AND TermNo = 0
AND PluEntryType <> 4
Group by
DATEPART(yyyy,SessionDate),
DATEPART(ww,SessionDate),
DATEADD(DAY, 1 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate +SessionTime AS DATE)),
DATEADD(DAY, 7 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate + SessionTime AS DATE)),
Case when #ConsolidateSites = 1 then 0 else SiteNo end,
Case when #ConsolidateSites = 1 then 'All' else CfgSites.Name end,
GroupNo,
GroupName,
DeptNo,
DeptName,
SDeptNo,
SDeptName,
PluNo,
PluDescription
order by WeekEnd
There are two issues here, the first is that I suspect you are defining 8 weeks of data as having 8 different values for DATEPART(WEEK, in which case you can replicate the root cause of the issue by looking at what ISO would define as the first week of 2015:
SET DATEFIRST 2;
SELECT Date, Week = DATEPART(WEEK, Date)
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Which gives:
Date Week
-----------------
2014-12-29 52
2014-12-30 53
2014-12-31 53
2015-01-01 1
2015-01-02 1
2015-01-03 1
2015-01-04 1
So although you only have 7 days, you have 3 different week numbers. The problem is that DATEPART(WEEK is quite a simplistic function, and will simply return the number of week boundaries passed since the first day of the year, a better function would be ISO_WEEK since this takes into account year boundaries nicely:
SET DATEFIRST 2;
SELECT Date, Week = DATEPART(ISO_WEEK, Date)
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Which gives:
Date Week
-----------------
2014-12-29 1
2014-12-30 1
2014-12-31 1
2015-01-01 1
2015-01-02 1
2015-01-03 1
2015-01-04 1
The problem is, that this does not take into account that the week starts on Tuesday, since the ISO week runs Monday to Sunday, you could adapt your usage slightly to get the week number of the day before:
SET DATEFIRST 2;
SELECT Date, Week = DATEPART(ISO_WEEK, DATEADD(DAY, -1, Date))
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Which would give:
Date Week
-----------------
2014-12-29 52
2014-12-30 1
2014-12-31 1
2015-01-01 1
2015-01-02 1
2015-01-03 1
2015-01-04 1
So Monday the 29th December is now recognized as the previous week. The problem is that there is no ISO_YEAR built in function, so you will need to define your own. This is a fairly trivial function, even so I almost never create scalar functions because they perform terribly, instead I use an inline table valued function, so for this I would use:
CREATE FUNCTION dbo.ISOYear (#Date DATETIME)
RETURNS TABLE
AS
RETURN
( SELECT IsoYear = DATEPART(YEAR, #Date) +
CASE
-- Special cases: Jan 1-3 may belong to the previous year
WHEN (DATEPART(MONTH, #Date) = 1 AND DATEPART(ISO_WEEK, #Date) > 50) THEN -1
-- Special case: Dec 29-31 may belong to the next year
WHEN (DATEPART(MONTH, #Date) = 12 AND DATEPART(ISO_WEEK, #Date) < 45) THEN 1
ELSE 0
END
);
Which just requires a subquery to be used, but the extra typing is worth it in terms of performance:
SET DATEFIRST 2;
SELECT Date,
Week = DATEPART(ISO_WEEK, DATEADD(DAY, -1, Date)),
Year = (SELECT ISOYear FROM dbo.ISOYear(DATEADD(DAY, -1, Date)))
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Or you can use CROSS APPLY:
SET DATEFIRST 2;
SELECT Date,
Week = DATEPART(ISO_WEEK, DATEADD(DAY, -1, Date)),
Year = y.ISOYear
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date)
CROSS APPLY dbo.ISOYear(d.Date) y;
Which gives:
Date Week Year
---------------------------
2014-12-29 52 2014
2014-12-30 1 2015
2014-12-31 1 2015
2015-01-01 1 2015
2015-01-02 1 2015
2015-01-03 1 2015
2015-01-04 1 2015
Even with this method, by simply getting a date 6 weeks ago you sill still end up with 7 weeks if the date you are using is not a Tuesday, because you will have 5 full weeks, and a part week at the start and a part week at the end, this is the second issue. So you need to make sure your start date is a Tuesday. The following will get you Tuesday of 7 weeks ago:
SELECT CAST(DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), DATEADD(WEEK, -6, GETDATE())) AS DATE);
The logic of this is explained better in this answer, the following is the part that will get the start of the week (based on your datefirst settings):
SELECT DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), GETDATE());
Then all I have done is substitute the second GETDATE() with DATEADD(WEEK, -6, GETDATE()) so that it is getting the start of the week 6 weeks ago, then there is just a cast to date to remove the time element from it.
This will get you current week + 5 previous weeks starting tuesday:
WHERE dateadd(week, datediff(d, 0, getdate()-1)/7 - 4, 1) <= yourdatecolumn
This will show examples:
DECLARE #wks int = 6 -- Weeks To Show
SELECT
dateadd(week, datediff(d, 0, getdate()-1)/7 - 4, 1) tuesday5weeksago,
dateadd(week, datediff(d, 0, getdate()-1)/7 - 5, 1) tuesday6weeksago,
dateadd(week, datediff(d, 0, getdate()-1)/7 - 6, 1) tuesday7weeksago,
dateadd(week, datediff(d, 0, getdate()-1)/7 - #wks + 1, 1) tuesdaydynamicweeksago
Result:
tuesday5weeksago tuesday6weeksago tuesday7weeksago tuesdaydynamicweeksago
2015-01-27 2015-01-20 2015-01-13 2015-01-20