Check Current date with last three days of month - sql-server

I want to check the current date if its equal to last three days of month excluding saturdays and sundays...
I can get the last day of month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
I am not sure how to check the getdate() with last three days of month excluding saturdays and sundays..
Will be of great help..
Thanks

-- make sure Sunday is the first day of the week:
SET DATEFIRST 7;
DECLARE
#today SMALLDATETIME,
#nextmonth SMALLDATETIME;
-- today at midnight is the number of days since 1900-01-01
-- the first day of nextmonth is one month after the first
-- day of the current month
SELECT
#today = DATEDIFF(DAY, '19000101', CURRENT_TIMESTAMP),
#nextmonth = DATEADD(MONTH, 1, #today-DAY(#today)+1);
-- so if today is greater than 3 days prior to the first of next month
-- and today is not a Saturday or a Sunday:
IF #today >= DATEADD(DAY, -3, #nextmonth)
AND DATEPART(WEEKDAY, #today) NOT IN (1,7)
BEGIN
PRINT 'Bazinga!';
END
If what you really meant is that you want the last three non-weekend days in the month, then:
SET DATEFIRST 7;
DECLARE
#today SMALLDATETIME,
#nextmonth SMALLDATETIME;
SELECT
#today = DATEDIFF(DAY, 0, GETDATE()),
#nextmonth = DATEADD(MONTH, 1, #today-DAY(#today)+1);
;WITH x AS
(
-- get the 5 days prior to the first day of next month:
SELECT TOP (5) d = DATEADD(DAY, -ROW_NUMBER() OVER
(ORDER BY [object_id]), #nextmonth) FROM sys.all_objects
),
y AS
(
-- get the last three days that aren't on Sat/Sun:
SELECT TOP (3) d FROM x
WHERE DATEPART(WEEKDAY, d) NOT IN (1,7)
ORDER BY d DESC
)
-- now find out if today is in those three days:
-- (by definition, today can't be Sat/Sun)
SELECT 'Bazinga!' FROM y WHERE d = #today;
This will yield no results if today is not in those three days.

This also gives last three days of month excluding saturday and sunday
SELECT LastFriDay,LastFriDay-1 LastThursday,LastFriDay-2 LastWednesday
FROM (
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-1 AS LastFriDay
UNION ALL
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-2 AS LastFriDay
UNION ALL
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-3 AS LastFriDay
UNION ALL
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-4 AS LastFriDay
UNION ALL
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-5 AS LastFriDay
UNION ALL
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-6 AS LastFriDay
UNION ALL
SELECT DATEADD(mm,1,GETDATE() - DAY(GETDATE())+1)-7 AS LastFriDay
) AS YourFridayTable
WHERE DATENAME(WeekDay,LastFriDay) = 'Friday'

Related

How to get Satuday's date of previous month in SQL Server? Can someone help me with this query?

Suppose now we are in September, I want output of the last Saturday date in the previous month, August, where 28-08-2021 falls under last Saturday of previous month in SQL Server
..fiddle..
select *, datename(weekday, pmlsat), dateadd(week, 1, pmlsat)
from
(
select _date,
--last saturday of previous month
dateadd(day, -datepart(weekday, dateadd(day, ##datefirst, eomonth(_date, -1)))%7, eomonth(_date, -1)) as pmlsat
from
(
select top(100) dateadd(month, row_number() over(order by ##spid), '20141215') as _date
from sys.all_objects
) as d
) as p
order by _date;
DECLARE #date1 DATETIME
SET #date1='2021-8-31'
WHILE Day(#date1) >= 1
BEGIN
IF (SELECT Datename(weekday, #date1)) = 'Saturday'
BREAK
SET #date1=Dateadd(dd, -1, #date1)
CONTINUE
END
SELECT Datename(weekday, #date1) AS 'Datename',
(SELECT CONVERT(NVARCHAR(20), #date1, 23)) AS 'DATE'
First, let's talk about how to get the beginning of this month. There are a multiple ways, I find DATEFROMPARTS() the most intuitive (see Simplify Date Period Calculations in SQL Server):
DECLARE #FirstOfMonth date = DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);
SELECT #FirstOfMonth;
-- result:
-- 2021-09-01
Now, the last Saturday in the previous month must be between 1 and 7 days before the first of this month. So we can generate a sequence of 7 consecutive numbers, and subtract those days from the first of the month, like this:
DECLARE #FirstOfMonth date = DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);
SELECT #FirstOfMonth;
;WITH n(n) AS
(
SELECT 1 UNION ALL
SELECT n + 1 FROM n WHERE n < 7
)
SELECT d = DATEADD(DAY, -n, #FirstOfMonth) FROM n;
/* result:
2021-08-31
2021-08-30
2021-08-29
2021-08-28
2021-08-27
2021-08-26
2021-08-25 */
To determine what a Saturday is, you either need to rely on DATEPART(WEEKDAY, date) - which in turn is affected by SET DATEFIRST, or you need to rely on DATENAME(WEEKDAY, date) - which in turn is affected by SET LANGUAGE. I will err toward language being more stable (English), so:
DECLARE #FirstOfMonth date = DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);
SELECT #FirstOfMonth;
;WITH n(n) AS
(
SELECT 1 UNION ALL
SELECT n + 1 FROM n WHERE n < 7
),
d(d) AS
(
SELECT DATEADD(DAY, -n, #FirstOfMonth)
FROM n
)
SELECT LastMonthLastSaturday = d
FROM d
WHERE DATENAME(WEEKDAY, d) = 'Saturday';
-- result:
-- 2021-08-28
But that is a subjective call - if you can't rely on one of those, get a calendar table, then it's simply something like:
SELECT LastMonthLastSaturday = MAX(TheDate)
FROM dbo.Calendar
WHERE TheDayOfWeekName = 'Saturday'
AND TheDate < DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);

How to get date from day name?

How can I get the date of specific day ? Like if I have Thursday or month number ?
If I give 12 for instance I want to get the date of 12th day of this month. Or if I give 'Sun' or 'Sat' is it possible to get the dates of these days ?
DATEFROMPARTS function can construct a date from day, month and year.
DATEPARTS does the opposite - gives you the day, month, year, hour, etc. of a date. Or you can use functions like YEAR, MONTH and DAY.
You can deconstruct the value returned by GETDATE function and construct whatever date you want. Here is for example how to get the date for 12th day of the current month:
select DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 12)
Converting 'Sun' or 'Sat' to date is a bit more difficult. First, they aren't quite deterministic. If today is Friday, "Sunday this week" means "next Sunday" in some parts of the world and "last Sunday" in others. You should implement your own logic based on the value returned by DATEPART(dw, GETDATE()) (which will give you the day of the week).
To find the weekday of the current month
DECLARE #daynumber INT = 12
SELECT datename(weekday, dateadd(d, #daynumber - 1, getdate()))
To find the dates of the current month of a given weekday
DECLARE #dayname char(3) = 'sat'
;WITH CTE as
(
SELECt TOP
(datediff(D, eomonth(getdate(), -1),eomonth(getdate())))
dateadd(d,row_number()over(ORDER BY 1/0),
eomonth(getdate(),-1))date
FROM
(values(1),(2),(3),(4),(5),(6))x(x),
(values(1),(2),(3),(4),(5),(6))y(x)
)
SELECT day(date) monthday, date
FROM CTE
WHERE left(datename(weekday, date),3) = #dayname
select sysdatetime(); --2018-12-13 16:29:56.0560574
---If I give 12 for instance I want to get the date of 12th day of this month.
declare #numDate int = 12;
select dateadd(m, datediff(m,0,getdate()),#numDate - 1 ); --2018-12-12 00:00:00.000
--Or if I give 'Sun' or 'Sat' is it possible to get the dates of these days ?
declare #text nvarchar(20) = 'Sunday';
declare #dateStart date = dateadd(month, datediff(month, 0, sysdatetime()), 0),
#days int =( select (DAY(dateadd(dd,-1,DATEADD(m,1,cast(2018 as varchar(4)) + '-' + cast(12 as varchar(2)) +'-01')))));
declare #dateEnd date = DATEADD(day,#days-1,#dateStart);
;WITH CTE (Dates,EndDate) AS
(
SELECT #dateStart AS Dates,#dateEnd AS EndDate
UNION ALL
SELECT DATEADD(day,1,Dates),EndDate
FROM CTE
WHERE DATEADD(day,1,Dates) <= EndDate
)
SELECT CTE.Dates, DATENAME(DW, CTE.Dates)
FROM CTE
where DATENAME(DW, CTE.Dates) = #text;
Result:
Dates,Day
2018/12/2,Sunday
2018/12/9,Sunday
2018/12/16,Sunday
2018/12/23,Sunday
2018/12/30,Sunday
-- Here is how to get week day name to week day number
DECLARE #T TABLE (Dow INT, NameOfDay VARCHAR(15), ShortName CHAR(3));
WITH Days AS
(
SELECT TOP 7
ROW_NUMBER() OVER(PARTITION BY object_id ORDER BY object_id) AS RowNo
FROM
sys.all_columns
)
INSERT INTO #T
SELECT
RowNo,
DATENAME(WEEKDAY, RowNo - 1),
LEFT(DATENAME(WEEKDAY, RowNo - 1), 3)
FROM
Days
SELECT
*
FROM
#T;
-- Here is how to get start of period
SELECT
DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) AS StartOfDay,
DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0) AS StartOfWeek,
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) AS StartOfMonth,
DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0) AS StartOfYear;
-- An example
WITH
StartPeriods AS
(
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0) AS StartOfWeek
),
SelectedDay AS
(
SELECT
Dow - 1 AS Dow,
(SELECT StartOfWeek FROM StartPeriods) AS StartOfWeek
FROM
#T
WHERE
ShortName = 'Wed'
)
SELECT
DATEADD(DAY, Dow, StartOfWeek)
FROM
SelectedDay;

SQL Server counting hours between dates excluding Fri 6pm - Mon 6am

I am looking for a SQL server function which can count the number of hours between 2 given datetime values, but excludes the hours between 6pm on Friday and 6am on Monday.
I'd like to be able to use this as a custom datediff, but also as a custom dateadd (eg adding 4 hours to 5pm a Friday, will return following Monday 9am)
I currently have something which excludes Sat/Sun based on the weekday number but this doesn't take the Fri/Mon hours into account.
This uses a number table. Adjust weekend start/end in parmeters:
declare #d1 as datetime = '2018-06-01 05:30:00'
, #d2 as datetime = '2018-06-18 19:45:00'
, #FridayWE as int = 18 --6pm
, #MondayWS as int = 6 --6am
;WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
select count(*) as HoursBetweenDatetimes
from (
SELECT dateadd(hour, ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n, dateadd(hour, datediff(hour, 0, #d1), 0)) as [DateHour]
FROM x ones, x tens, x hundreds, x thousands
) a
where not ((DATEPART(dw,[DateHour]) = 6 and DATEPART(hour,[DateHour]) >= #FridayWE)
or (DATEPART(dw,[DateHour]) = 7 )
or (DATEPART(dw,[DateHour]) = 1 )
or (DATEPART(dw,[DateHour]) = 2 and DATEPART(hour,[DateHour]) < #MondayWS))
and [DateHour] < #d2
This is another option you can use, with a calendar table.
This is the generation of the calendar table. For this case it has just days from monday to friday and from 9am to 6pm, one day per row (this can be additional columns for your regular calendar table).
IF OBJECT_ID('tempdb..#WorkingCalendar') IS NOT NULL
DROP TABLE #WorkingCalendar
CREATE TABLE #WorkingCalendar (
StartDateTime DATETIME,
EndDateTime DATETIME)
SET DATEFIRST 1 -- 1: Monday, 7: Sunday
DECLARE #StartDate DATE = '2018-01-01'
DECLARE #EndDate DATE = '2025-01-01'
;WITH RecursiveDates AS
(
SELECT
GeneratedDate = #StartDate
UNION ALL
SELECT
GeneratedDate = DATEADD(DAY, 1, R.GeneratedDate)
FROM
RecursiveDates AS R
WHERE
R.GeneratedDate < #EndDate
)
INSERT INTO #WorkingCalendar (
StartDateTime,
EndDateTime)
SELECT
StartDateTime = CONVERT(DATETIME, R.GeneratedDate) + CONVERT(DATETIME, '09:00:00'),
EndDateTime = CONVERT(DATETIME, R.GeneratedDate) + CONVERT(DATETIME, '18:00:00')
FROM
RecursiveDates AS R
WHERE
DATEPART(WEEKDAY, R.GeneratedDate) BETWEEN 1 AND 5 -- From Monday to Friday
OPTION
(MAXRECURSION 0)
This is the query to calculate time differences between 2 datetimes. You can change the HOUR for anything you want, in all 3 places (MINUTE, SECOND, etc.) and the result will be displayed in that unit.
DECLARE #FromDate DATETIME = '2018-06-15 18:00:00'
DECLARE #ToDate DATETIME = '2018-06-18 10:00:00'
;WITH TimeDifferences AS
(
-- Date completely covered
SELECT
Difference = DATEDIFF(
HOUR,
W.StartDateTime,
W.EndDateTime)
FROM
#WorkingCalendar AS W
WHERE
W.StartDateTime >= #FromDate AND
W.EndDateTime <= #ToDate
UNION ALL
-- Filter start date partially covered
SELECT
Difference = DATEDIFF(
HOUR,
#FromDate,
CASE WHEN W.EndDateTime > #ToDate THEN #ToDate ELSE W.EndDateTime END)
FROM
#WorkingCalendar AS W
WHERE
#FromDate BETWEEN W.StartDateTime AND W.EndDateTime
UNION ALL
-- Filter end date partially covered
SELECT
Difference = DATEDIFF(
HOUR,
CASE WHEN W.StartDateTime > #FromDate THEN W.StartDateTime ELSE #FromDate END,
#ToDate)
FROM
#WorkingCalendar AS W
WHERE
#ToDate BETWEEN W.StartDateTime AND W.EndDateTime
)
SELECT
Total = SUM(T.Difference)
FROM
TimeDifferences AS T
This approach will consider each day from the calendar table, so if a particular day you have reduced hours (or maybe none from a Holiday) then the result will consider it.
You can use this query to add hours. Basically split each calendar range by hour, then use a row number to determine the amount of hours to add. Is this case you can't simply change the HOUR for MINUTE, it will require a few tweaks here and there if you need it.
DECLARE #FromDate DATETIME = '2018-06-14 12:23:12.661'
DECLARE #HoursToAdd INT = 15
;WITH RecursiveHourSplit AS
(
SELECT
StartDateTime = W.StartDateTime,
EndDateTime = W.EndDateTime,
HourSplitDateTime = W.StartDateTime
FROM
#WorkingCalendar AS W
UNION ALL
SELECT
StartDateTime = W.StartDateTime,
EndDateTime = W.EndDateTime,
HourSplitDateTime = DATEADD(HOUR, 1, W.HourSplitDateTime)
FROM
RecursiveHourSplit AS W
WHERE
DATEADD(HOUR, 1, W.HourSplitDateTime) < W.EndDateTime
),
HourRowNumber AS
(
SELECT
R.HourSplitDateTime,
RowNumber = ROW_NUMBER() OVER (ORDER BY R.HourSplitDateTime ASC)
FROM
RecursiveHourSplit AS R
WHERE
#FromDate < R.HourSplitDateTime
)
SELECT
DATETIMEFROMPARTS(
YEAR(R.HourSplitDateTime),
MONTH(R.HourSplitDateTime),
DAY(R.HourSplitDateTime),
DATEPART(HOUR, R.HourSplitDateTime),
DATEPART(MINUTE, #FromDate),
DATEPART(SECOND, #FromDate),
DATEPART(MILLISECOND, #FromDate))
FROM
HourRowNumber AS R
WHERE
R.RowNumber = #HoursToAdd
You can use similar logic to substract amount of hours by creating the row number with the rows that have datetimes before the supplied datetime (instead of after).

Find the First Wednesday after the last Tuesday of last financial month

One of my clients defines (for strange financial reasons) a financial month as a period of time that begins the Wednesday immediately after the last Tuesday of a Month (inclusive) and lasts until the last tuesday of the following month (inclusive).
I need to find the start of the last and the current financial month.
Some examples:
if today is September 23rd 2015 i need to get July 29th and August 26th because the current financial month goes from August 26th to September 29th.
If today is September 30th 2015 I need to get August 26th to September 30th.
I have different clients with different definitions and this means that some of them are using Wednesday and others are using Monday so i need this day to be a parameter, like Monday = 1 and Wednesday = 3. I call it FDOM, FirstDayOfMonth.
My work so far focused on using the formulas i found around with first and last days of current and last month, modified to take into account FDOM. I managed to get last Wednesday of Last Month but this sometimes is not correct because I am considering a day of the month that belongs to a solar month but also to the next financial month, like September 30th belongs to solar September but to Financial October, as financial October begins September 30th.
DECLARE #BASE AS DateTime = '19000101 00:00'
DECLARE #FDOM AS INT = 3 --Wednesday
DECLARE #Datevalue AS DATE = GETDATE()
SET DATEFIRST #FDOM
select DATEADD(D,1-(DATEPART(dw,DATEADD(D,-1,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #Datevalue) , #BASE)))),DATEADD(D,-1,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #Datevalue) , #BASE)))
This gives me the first wednesday after the last tuesday of last month and this would be correct from September 1st to September 29th (it gives August 26th) as "the beginning of the current financial month". But it would be wrong on September 30th as it should give September 30th and also wrong from August 26th till the end of August as it should give August 26th but instead gives July 29th.
I think this answers your requirements. Its quite long but hopefully, by breaking things out and naming things, I'm making it clear how we get to the final answer, and so if it's not quite right, it can be adapted:
declare #FDOM int
set #FDOM = 3 --Wednesday. 0 = Sunday, 6 = Saturday
declare #KnownDay datetime
set #KnownDay = DATEADD(day,#FDOM - 1,'20150301') --Offset from a "known good" Sunday to the day before FDOM
declare #EOLastDec datetime
set #EOLastDec = DATEADD(year,DATEDIFF(year,'20010101',GETDATE()),'20001231')
declare #Today datetime
set #Today = DATEADD(day,DATEDIFF(day,0,GETDATE()),0) --You can change this to test other key dates
;With Numbers(n) as (--If you have a numbers table, you can skip this CTE
select ROW_NUMBER() OVER (ORDER BY so1.object_id) - 1
from sys.objects so1 cross join sys.objects so2
), LastOfMonths as (
select DATEADD(month,n,#EOLastDec) as LOM
from Numbers
where n between 0 and 13
), LastImportant as (
select DATEADD(day,-n,LOM) as EOFMonth
from LastOfMonths cross join Numbers
where n between 0 and 6 and
DATEPART(weekday,DATEADD(day,-n,LOM)) = DATEPART(weekday,#KnownDay)
)
select DATEADD(day,1,li0.EOFMonth) as StartOfMonth,DATEADD(day,1,li1.EOFMonth) as EndOfMonth
from
LastImportant li1
cross join
LastImportant li2
left join
LastImportant li1_anti
on
li1.EOFMonth < li1_anti.EOFMonth and
li1_anti.EOFMonth <= #Today
left join
LastImportant li2_anti
on
li2.EOFMonth > li2_anti.EOFMonth and
li2_anti.EOFMonth >= #Today
inner join
LastImportant li0
on
li0.EOFMonth < li1.EOFMonth
left join
LastImportant li0_anti
on
li0_anti.EOFMonth < li1.EOFMonth and
li0.EOFMonth < li0_anti.EOFMonth
where
li1.EOFMonth <= #Today and
li2.EOFMonth >= #Today and
li1_anti.EOFMonth is null and
li2_anti.EOFMonth is null and
li0_anti.EOFMonth is null
Hopefully, the CTEs are reasonably explanatory. We generate a numbers table, and then we calculate the last day of each month, and from there, we step up to 6 days backwards to locate a day of the right type (i.e. a Tuesday, if #FDOM is 3)
I originally had a simpler final query using just li1 and li2 (and li1_anti and li2_anti), but realised that the query was just finding the current financial month - so I've added another couple of joins (using li0 and li0_anti) to find the start of the previous financial month.
Calculate the start date from previous month and the last day from current month and used a CTE to generate all dates between them. Later, get the MAX weekday from both months.
DECLARE #CurrentDate DATE = '2015-08-23'
DECLARE #StartDate DATE,
#EndDate DATE,
#MonthEnd INT = 3
-- Get the first day from previous month and last day from current month
SELECT #StartDate = DATEADD(MONTH , DATEDIFF(MONTH, 0, #CurrentDate)-1, 0),
#EndDate = DATEADD(SECOND,-1,
DATEADD(MONTH , DATEDIFF(MONTH, 0, #CurrentDate)+1,0))
;WITH Calendar AS
( -- Generate all dates between #StartDate and #EndDate
SELECT #StartDate [Date]
UNION ALL
SELECT DATEADD(D, +1, Calendar.[Date])
FROM Calendar
WHERE Calendar.[Date] < #EndDate
)
SELECT DATEADD(DAY, +1, MAX(StartDate.[Date])) StartDate,
DATEADD(DAY, +1, MAX(EndDate .[Date])) EndDate
FROM Calendar StartDate,
Calendar EndDate
WHERE -- Get the max weekday from previous month
DATEPART(MONTH , StartDate.[Date]) = DATEPART(MONTH, #StartDate) AND
DATEPART(WEEKDAY, StartDate.[Date]) = #MonthEnd AND
-- Get the max weekday from current month
DATEPART(MONTH , EndDate .[Date]) = DATEPART(MONTH, #EndDate) AND
DATEPART(WEEKDAY, EndDate .[Date]) = #MonthEnd
Try this. You can use EOMONTH function to get the end of month on Sql Server 2012 or above.
Click to see the fiddle demo.
DECLARE #date DATETIME = GETDATE()
DECLARE #LastMonthEnd DATETIME = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, #date), 0))
DECLARE #CurrentMonthEnd DATETIME = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, #date) + 1, 0))
SET DATEFIRST 1
;WITH CTE1 AS
(
SELECT 1 number, DATEPART(WEEKDAY, #LastMonthEnd) FirstDay,
DATEPART(WEEKDAY, #CurrentMonthEnd) LastDay
UNION ALL
SELECT 1+number, DATEPART(WEEKDAY, DATEADD(DAY, -number, #LastMonthEnd)),
DATEPART(WEEKDAY, DATEADD(DAY, -number, #CurrentMonthEnd))
FROM CTE1
WHERE number < 7
)
SELECT DATEADD(DAY, -(SELECT Number FROM CTE1 WHERE FirstDay = 3), #LastMonthEnd) StartDate,
DATEADD(DAY, -(SELECT Number FROM CTE1 WHERE LastDay = 3), #CurrentMonthEnd) EndDate
After a lot of effort I managed to find an expression that DOES NOT use CTE as i am not sure i can't use CTE in all the places i will have to employ this.
So basically first i understand with a CASE if the date i am considering is before or after the last Wednesday of the Month it belongs to. Then i return the last wednseday of two and of one month ago OR the last wednesday of one month ago and of this month.
This works also changing FDOM and i tested it for several months of this year. It seems to always work.
Probably the use of EOMonth would shorten it but i have to verify i can use it in my server.
I am sorry i just specified as a requirement that i can't use a CTE only in the comments but thank you for your help
DECLARE #datevalue AS Datetime = getdate()
DECLARE #BASE AS DateTime = '19000101 00:00'
DECLARE #FDOM AS INT = 3 --1 is for Monday
SET DATEFIRST #FDOM
SELECT CASE WHEN (#datevalue < DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE)))
THEN(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 1, #BASE)))
ELSE(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 0, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) - 0, #BASE)))
END AS [Start of Last Financial Month]
,CASE WHEN (#datevalue < DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE)))
THEN(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 0, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 0, #BASE)))
ELSE(DATEADD(D, 1-(DATEPART(dw,DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE))),DATEADD(MONTH, DATEDIFF(MONTH, #BASE, #datevalue) + 1, #BASE)))
END AS [Start of Current Financial Month]

how to get data of current week only in SQL server?

I want records from table which stores the current date when a record is inserted with in current week only.
I have tried:
SELECT PId
,WorkDate
,Hours
,EmpId
FROM Acb
WHERE EmpId=#EmpId AND WorkDate BETWEEN DATEADD(DAY, -7, GETDATE()) AND GETDATE()
Do it like this:
SET DATEFIRST 1 -- Define beginning of week as Monday
SELECT [...]
AND WorkDate >= dateadd(day, 1-datepart(dw, getdate()), CONVERT(date,getdate()))
AND WorkDate < dateadd(day, 8-datepart(dw, getdate()), CONVERT(date,getdate()))
Explanation:
datepart(dw, getdate()) will return the number of the day in the current week, from 1 to 7, starting with whatever you specified using SET DATEFIRST.
dateadd(day, 1-datepart(dw, getdate()), getdate()) subtracts the necessary number of days to reach the beginning of the current week
CONVERT(date,getdate()) is used to remove the time portion of GETDATE(), because you want data beginning at midnight.
A better way would be
select datepart(ww, getdate()) as CurrentWeek
You can also use wk instead of ww.
Datepart Documentation
Its Working For Me.
Select * From Acb Where WorkDate BETWEEN DATEADD(DAY, -7, GETDATE()) AND DATEADD(DAY, 1, GETDATE())
You have to put this line After the AND Clause AND DATEADD(DAY, 1, GETDATE())
datepart(dw, getdate()) is the current day of the week, dateadd(day, 1-datepart(dw, getdate()), getdate()) should be the first day of the week, add 7 to it to get the last day of the week
You can use following query to extract current week:
select datepart(dw, getdate()) as CurrentWeek
SET DATEFIRST 1;
;With CTE
AS
(
SELECT
FORMAT(CreatedDate, 'MMMM-yyyy') as Months,
CASE
WHEN YEAR(DATEADD(DAY, 1-DATEPART(WEEKDAY, Min(CreatedDate)), Min(CreatedDate))) < YEAR(Min(CreatedDate))
THEN FORMAT(DATEADD(YEAR, DATEDIFF(YEAR, 0,DATEADD(YEAR, 0 ,GETDATE())), 0) ,'MMM dd') + ' - ' + FORMAT(DATEADD(dd, 7-(DATEPART(dw, Min(CreatedDate))), Min(CreatedDate)) ,'MMM dd')
ELSE
FORMAT(DATEADD(DAY, 1-DATEPART(WEEKDAY, Min(CreatedDate)), Min(CreatedDate)) ,'MMM dd') + ' - ' + FORMAT(DATEADD(dd, 7-(DATEPART(dw, Min(CreatedDate))), Min(CreatedDate)) ,'MMM dd')
END DateRange,
Sum(ISNULL(Total,0)) AS Total,
sum(cast(Duration as int)) as Duration
FROM TL_VriandOPI_Vendorbilling where VendorId=#userID and CompanyId=#CompanyID
Group By DATEPART(wk, CreatedDate) ,FORMAT(CreatedDate, 'MMMM-yyyy')
)
SELECT Months,DateRange,Total,Duration,
case when DateRange=(select FORMAT(DATEADD(DAY, 1-DATEPART(WEEKDAY, Min(getdate())), Min(getdate())) ,'MMM dd') + ' - ' +
FORMAT(DATEADD(dd, 7-(DATEPART(dw, Min(getdate()))), Min(getdate())) ,'MMM dd'))
then 1 else 0 end as Thisweek
FROM CTE order by Months desc
Using DATEDIFF works as well, however a bit hacky since it doesn't care about datefirst:
set datefirst 1; -- set monday as first day of week
declare #Now datetime = '2020-09-28 11:00';
select *
into #Temp
from
(select 1 as Nbr, '2020-09-22 10:00' as Created
union
select 2 as Nbr, '2020-09-25 10:00' as Created
union
select 2 as Nbr, '2020-09-28 10:00' as Created) t
select * from #Temp where DATEDIFF(ww, dateadd(dd, -##datefirst, Created), dateadd(dd, -##datefirst, #Now)) = 0 -- returns 1 result
select * from #Temp where DATEDIFF(ww, dateadd(dd, -##datefirst, Created), dateadd(dd, -##datefirst, #Now)) = 1 -- returns 2 results
drop table #Temp

Resources