Getting days since start of week (excluding weekends) - sql-server

This is part of a query that is calculating the total revenue for a contract based on the time-frame "This Week" along with the start and end dates of the contract (billed hourly).
SELECT (ChargeRate - PayRate) * 8 *
CASE
WHEN ContractStartDate <= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractEndDate >= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
WHEN ContractEndDate <= CURRENT_TIMESTAMP
AND ContractEndDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractStartDate <= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, ContractEndDate), ContractEndDate), ContractEndDate)
WHEN ContractStartDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractStartDate <= CURRENT_TIMESTAMP
AND ContractStartDate >= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, ContractStartDate, CURRENT_TIMESTAMP)
WHEN ContractEndDate <= CURRENT_TIMESTAMP
AND ContractEndDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractStartDate >= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, ContractStartDate, ContractEndDate)
ELSE DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
END
What i am struggling with is how i can exclude Saturday and Sunday so the count never goes past 5 and where Sunday is not the start of the week but instead Monday. So the number of days worked would end up being [ Monday = 1, Tuesday = 2 ... Friday = 5, Saturday = 5, Sunday = 5 ] based on what day the query is run.
What happens at the moment is that if these graphs are run on Saturday the calculation uses 6 days, if its run on Sunday the calculation uses 0 days. Every day during the week is correct, this can be seen with the following query:
DECLARE #StartDate DATETIME = '2019-12-1'
DECLARE #StartDate2 DATETIME = '2019-11-30'
SELECT DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, #StartDate), #StartDate), #StartDate)
SELECT DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, #StartDate2), #StartDate2), #StartDate2)
Results should be 0 and 6.
The only solution i can come up with is to nest the case statement and check if the value = 0 or 6 and change it to a 5, like so:
WHEN ContractStartDate <= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractEndDate >= CURRENT_TIMESTAMP
THEN
CASE
WHEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP) IN (0,6)
THEN 5
ELSE DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
END
which works but is a bit messy and i am interested to see if there is a better solution to this.

Here's one way, borrowed from Jeff Moden via SQLServerCentral. (I'd comment this reply, but I don't have enough whacky points :( )
--count weekdays between two dates
DECLARE #StartDate DATETIME = '2019-11-01'
DECLARE #EndDate DATETIME = '2019-11-30'
SELECT (DATEDIFF(DD, #StartDate, #EndDate) + 1) --Total days in period, including weekends
-(DATEDIFF(WK, #StartDate, #EndDate) * 2) --minus number of whole weekends in the period * 2 days
-(CASE WHEN DATENAME(DW, #StartDate) = 'Sunday' THEN 1 ELSE 0 END) --minus 1 if the period starts on a Sunday
-(CASE WHEN DATENAME(DW, #EndDate) = 'Saturday' THEN 1 ELSE 0 END) --minus 1 if the period ends on a Saturday
Of course, there are issues here, such as the use of English day names that won't travel well, but those can be worked around if necessary.
I have variation of this built into a "WeekdayCount" function that comes in very handy!
Way more detail here: https://www.sqlservercentral.com/articles/calculating-work-days

additional solution to already posted by #tim-monfries:
DECLARE #StartDate DATETIME = '2019-11-01';
DECLARE #EndDate DATETIME = '2019-11-30';
WITH cte AS
(
SELECT #StartDate AS SomeDate
UNION ALL
SELECT SomeDate+1 FROM cte WHERE SomeDate < #EndDate
)
SELECT COUNT(*)
FROM cte
WHERE DATENAME(dw, SomeDate) NOT IN ('Sunday', 'Saturday');

Related

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;

Calculate Total Working Days of month

I have this table where I am specifying Holidays in week. I want to calculate total working days between 2 specific dates using these fields.
CREATE TABLE [tbl_Shift](
[OffDay1] [nvarchar](25) NOT NULL CONSTRAINT [DF_tbl_Shift_OffDay1] DEFAULT (N'Sunday'),
[IsAlternateOffDay2] [bit] NULL,
[OffDay2] [nvarchar](25) NULL
)
INSERT INTO [tbl_Shift] VALUES ('Sunday', 'True', 'Saturday')
I have this query written but I am not able to get correct days. It should give 23 days as there are 2 holidays in each week and 31 days in total but I'm getting 26 days.
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = '2018/05/01'
SET #EndDate = '2018/05/31'
SELECT
(DATEDIFF(dd, #StartDate, #EndDate+1)) -(DATEDIFF(wk, #StartDate, #EndDate))
-(CASE WHEN IsAlternateOffday2 = 1 THEN 1 END) FROM HRM.tbl_Shift
this will give 23:
SELECT
(DATEDIFF(dd, #StartDate, #EndDate+1)) -(DATEDIFF(wk, #StartDate, #EndDate))
-ISNULL((CASE WHEN IsAlternateOffday2 = 1 THEN (DATEDIFF(wk, #StartDate, #EndDate)) END), 0)
FROM HRM.tbl_Shift
This subtracts 2 days for every weekend. Check your server config if Sunday is first or last day of the week. This can throw things off by a weekend.
SELECT DATEPART(WEEKDAY,'20180506') --Checks if Sunday is Day 1 or Day 7
DECLARE #start DATETIME = '20180501'
DECLARE #end DATETIME = '20180531'
SELECT DATEDIFF(DAY,#start,#end+1) - (DATEDIFF(WEEK,#start,#end+1)*2)
UPDATE:
Use COALESCE to replace NULLS with an alternative value.
DECLARE #offdate DATETIME = NULL
SELECT COALESCE(#offdate,GETDATE())
Try This
DECLARE #StartDate DATE ='2018-05-01',
#EndDate DATE ='2018-05-31'
;WITH CTE
AS
(
SELECT DATEADD(DD,Number-1,#StartDate) MOnthDates,
DATENAME(DW,DATEADD(DD,Number-1,#StartDate)) As DayNAmes,
CASE WHEN DATENAME(DW,DATEADD(DD,Number-1,#StartDate)) IN ('Saturday','Sunday') THEN 0 ELSE 1 END WeekDays
FROM master.dbo.spt_values
WHERE [Type]='P'
AND Number Between 1 AND 10000
)
SELECT COUNT(WeekDays) AS WeekDaysCount
FROM CTE
WHERE WeekDays<>0
AND MOnthDates Between #StartDate AND DATEADD(DAY,1,#EndDate)
Result
WeekDaysCount
-------------
23
Demo:http://rextester.com/TOLYT35075
This was what I created after reviewing the answers. I needed the number of days per month for several months. The below will provide that, and insert it into the #MonthDayCount table. Note: I named a field Month, even though that is a SQL Server defined term; you can change it if needed.
You must enter the first day of the month and the last for it to count the first and last month correctly. If you entered 1/2/2022, it would result in January being short one day.
DECLARE #StartDate DATE = '1/01/2021'--The start of the first month the number of days are needed for.
DECLARE #EndDate DATE = '1/31/2021'--The end of the first month the number of days are needed for.
DECLARE #FinalDate DATE = '12/31/2022'--This is the last month that will be inserted. Includes this month.
IF OBJECT_ID('tempdb..#MonthDayCount', 'U') IS NOT NULL
DROP TABLE #MonthDayCount;
CREATE TABLE #MonthDayCount
(
[Month] VARCHAR(MAX),
[# of WeekDays] INT,
[EOM] DATE
)
WHILE #StartDate <= #FinalDate
BEGIN
INSERT INTO
#MonthDayCount
VALUES (
DATENAME(m,#StartDate),
(
DATEDIFF(dd, #StartDate, #EndDate) + 1)
-(DATEDIFF(wk, #StartDate, #EndDate) * 2)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #EndDate) = 'Saturday' THEN 1 ELSE 0 END
),
#EndDate
)
SET #StartDate = DATEADD(m,1,#StartDate)
SET #EndDate = EOMONTH(#EndDate,1)
END
MS SQL Server query to find count of all the working days (non Saturdays and Sundays) in current month.
Works in SQL Server, Azure Synapse Analytics
Note:
Change the getdate() as per your need.
SELECT Day(Eomonth(Getdate())) - ( Datediff(d, Dateadd(d, Datediff(d, -1,
Dateadd(month, Month(
Getdate()) - 1 + (
Year(Getdate()
) - 1900 )
*
12, 6)) / 7 * 7, -1),
Dateadd(m, 1, Dateadd(
month,
Month(Getdate())
- 1 +
(
Year(Getdate()) - 1900 )
*
12, 6
)
)) / 7 +
Datediff(d, Dateadd(d, Datediff(d, -1,
Dateadd(
month,
Month(Getdate()) - 1 + (
Year(Getdate()
) - 1900 )
*
12, 7)) / 7 * 7, -1), Dateadd(m, 1,
Dateadd(month, Month(Getdate()) - 1 +
(
Year(Getdate()) - 1900 ) *
12, 7)
)) / 7 ) AS Num_Working_Days

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]

Get date with some criteria in SQL server

What I want is the EmployeeName from the emp_mst table with some condition which is given below:-
All EmployeeName for last 7 months from the current date and also less 15 days.
from the below query I am getting the result for the last month, but I want this for the last 6 months
select DATEADD(month, -1, GETDATE()- 15)
I am using sql server 2008
UPDATED PROCEDURE
SELECT * FROM (SELECT CASE
WHEN (SELECT Isnull(Sum(total_day), 0)
FROM xxacl_erp_ab_pl_count_view
WHERE emp_card_no = em.emp_card_no) > 7 THEN
'DOC Exteded By 1 month. Reason:- Taken leave='
+ CONVERT(VARCHAR, (SELECT Sum(total_day) FROM
xxacl_erp_ab_pl_count_view
WHERE emp_card_no = em.emp_card_no))
+
' which is > 7. Actual DOC='
+ CONVERT(VARCHAR, Dateadd(mm, em.probation_period, em.date_of_joining), 103)
+ ''
ELSE 'N/A'
END Remark,
em.*
FROM emp_mst em
LEFT JOIN company_mst comp
ON em.comp_mkey = comp.mkey
AND comp.fa_year = 2008
AND company_name NOT LIKE '%HELIK%'
WHERE em.status IN ( 'A' ) --and em.emp_type='E'
AND em.emp_card_no != 9999
AND em.resig_date IS NULL
AND CONVERT(DATETIME, em.date_of_joining, 103) >=
CONVERT(DATETIME,
Dateadd(m, -6, Getdate()), 103)
AND em.emp_card_no NOT IN (SELECT emp_card_no
FROM p_emp_confirmation_hdr
WHERE delete_flag = 'N'
AND hr_flag = 'Y')) pp
WHERE remark = 'N/A'
Casting to date to avoid calculating with timestamps
WHERE
yourdate >= dateadd(m, -6, datediff(d, 15, getdate())) and
yourdate < dateadd(d, -15, datediff(d, 0, getdate()))
Changed answer to adjust for you using sqlserver 2005 or older
Added 15 days extra to the interval
SELECT [emp_name]
FROM [TABLE]
WHERE [DateColumn] BETWEEN DATEADD(MONTH, -6, CAST(GETDATE() AS DATE))
AND DATEADD(DAY, -15, CAST(GETDATE() AS DATE))
This will show you employees who were added between six months ago and 15 days ago, for example, running that today would give you employees from the range 2014-12-24 and 2015-06-09.
EDIT: For SQL Server 2005 and earlier:
SELECT [emp_name]
FROM [TABLE]
WHERE [DateColumn] BETWEEN DATEADD(MONTH, -6, cast(convert(char(11), getdate(), 113) as datetime))
AND DATEADD(DAY, -15, cast(convert(char(11), getdate(), 113) as datetime))

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