How do I get start date and end date of a month by month name? Not by date, not by month number.
For example, this gets me first day of current month. Input is a date type, not string like I want it to be.
SELECT DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)
What I want is to input month name in string like 'March' not 3 and get 2016/03/01 and 2016/03/31. I'd really be overwhelmed and appreciate any/all help.
You can create a CTE to get the month number:
DECLARE #month VARCHAR(10) = 'March';
WITH CteMonths(n, m) AS(
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'April' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'June' UNION ALL
SELECT 7, 'July' UNION ALL
SELECT 8, 'August' UNION ALL
SELECT 9, 'September' UNION ALL
SELECT 10, 'October' UNION ALL
SELECT 11, 'November' UNION ALL
SELECT 12, 'December'
)
SELECT
DATEADD(MONTH, n - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)),
DATEADD(DAY, -1, DATEADD(MONTH, n, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)))
FROM CteMonths
WHERE m = #month
Related
For example consider the April 2023. In this year the Monday dates are 3, 10, 17, and 24. Now I want to get the date 10 position of April.
My target result is: April 10 = second or 2
SELECT (DAY('2023-04-10') - 1) / 7 + 1
Position outputs the searched number for a date
WITH CTE_DATES
AS(
SELECT CAST(DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) -1, 0) AS DATE) AS [DATE] -- start previous month
UNION ALL
SELECT CAST(DATEADD(DD, 1, [DATE]) AS DATE)
FROM [CTE_DATES]
WHERE [DATE] < CAST(DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 0, 0)) AS DATE) -- end previous month
)
SELECT
[date]
,DATENAME(WEEKDAY, [date]) AS 'Weekday'
,DATEPART(WEEKDAY, [date]) AS 'Day'
,ROW_NUMBER() OVER (ORDER BY [date] ASC) AS 'POSITION'
FROM [CTE_DATES]
WHERE DATEPART(WEEKDAY, [date]) IN (1)
I have to find weekly average from table given below (only work days - monday to friday). Number I am searching average is AVAI_NUM. I have to calculate average of AVAI_NUM for each week in given period.
Example:
If period is january 2016:
declare #dDateFrom date = cast('2016-01-01' as date)
declare #dDateTo date = cast('2016-01-31' as date)
Table looks like this:
declare #scavai table
(
avai_key int,
avai_dat date,
avai_num int
)
Fill table with data:
insert into #scavai(avai_Key, avai_dat, avai_num)
select 1, cast('2016-01-01' as date), 3
union all
select 1, cast('2016-01-02' as date), 2
union all
select 1, cast('2016-01-03' as date), 5
union all
select 1, cast('2016-01-04' as date), 6
union all
select 1, cast('2016-01-05' as date), 1
union all
select 1, cast('2016-01-06' as date), 8
union all
select 1, cast('2016-01-07' as date), 4
union all
select 1, cast('2016-01-08' as date), 3
union all
select 1, cast('2016-01-09' as date), 2
union all
select 1, cast('2016-01-10' as date), 1
union all
select 1, cast('2016-01-11' as date), 9
union all
select 1, cast('2016-01-12' as date), 7
union all
select 1, cast('2016-01-13' as date), 3
union all
select 1, cast('2016-01-14' as date), 8
union all
select 1, cast('2016-01-15' as date), 3
union all
select 1, cast('2016-01-16' as date), 2
union all
select 1, cast('2016-01-17' as date), 3
union all
select 1, cast('2016-01-18' as date), 1
union all
select 1, cast('2016-01-19' as date), 4
union all
select 1, cast('2016-01-20' as date), 5
union all
select 1, cast('2016-01-21' as date), 7
union all
select 1, cast('2016-01-22' as date), 3
union all
select 1, cast('2016-01-23' as date), 3
union all
select 1, cast('2016-01-25' as date), 3
union all
select 1, cast('2016-01-26' as date), 3
I know how to calculate number of weeks in given period:
select DATEDIFF(ww, '2016-01-01', '2016-01-31')
But I don't know how to calculate AVAI_NUM for work days in each week and divide this with number of days in particular week and then summarize all of this and divide with number of weeks?
try,
select *,
AVG(cast(avai_num as decimal)) over
(partition by datepart(week, avai_dat) order by (select 1)) avg1
from #scavai
where avai_dat between #dDateFrom and #dDateTo
order by avai_dat
I am trying to find attendance for any month like this:
DECLARE #StartDate DATE
DECLARE #EndDate DATE
SET #StartDate = '2016/10/01'
SET #EndDate = '2016/10/31'
SELECT
StaffAttendance.StaffId, DATENAME(MONTH, #StartDate) AS [ForMonth],
(DATEDIFF(dd, #StartDate, #EndDate) + 1)
-(DATEDIFF(wk, #StartDate, #EndDate) * 1)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END) AS TotalWorkingDays,
SUM(StaffAttendance.AttendanceStatusId) AS TotalDaysWorked FROM StaffAttendance WHERE [Date] BETWEEN #StartDate AND #EndDate AND StaffAttendance.AttendanceStatusId = 1 GROUP BY StaffAttendance.StaffId
And this is what I am getting, which is just fine.
What I want to do next is omit the date range (#StartDate DATE, #EndDate DATE) and use month name instead like - 'October' and not month number like '10.' So that user gives a month name and start and end dates for that month are automatically calculated. I got help for that by Felix Pamittan.
DECLARE #month VARCHAR(9) = 'february';
WITH CteMonths(n, m) AS(
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'April' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'June' UNION ALL
SELECT 7, 'July' UNION ALL
SELECT 8, 'August' UNION ALL
SELECT 9, 'September' UNION ALL
SELECT 10, 'October' UNION ALL
SELECT 11, 'November' UNION ALL
SELECT 12, 'December'
)
SELECT
DATEADD(MONTH, n - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)) AS StartDate,
DATEADD(DAY, -1, DATEADD(MONTH, n, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0))) AS EndDate
FROM CteMonths
WHERE m = #month
Now, how do I combine these two and get same result as above?
Use CROSS APPLY:
DECLARE #month VARCHAR(9) = 'february';
WITH CteMonths(n, m) AS(
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'April' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'June' UNION ALL
SELECT 7, 'July' UNION ALL
SELECT 8, 'August' UNION ALL
SELECT 9, 'September' UNION ALL
SELECT 10, 'October' UNION ALL
SELECT 11, 'November' UNION ALL
SELECT 12, 'December'
)
SELECT
sa.StaffId,
DATENAME(MONTH, t.StartDate) AS [ForMonth],
(DATEDIFF(dd, t.StartDate, t.EndDate) + 1)
- (DATEDIFF(wk, t.StartDate, t.EndDate) * 1)
- (CASE WHEN DATENAME(dw, t.StartDate) = 'Sunday' THEN 1 ELSE 0 END) AS TotalWorkingDays,
SUM(sa.AttendanceStatusId) AS TotalDaysWorked
FROM StaffAttendance sa
CROSS APPLY(
SELECT
DATEADD(MONTH, n - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)) AS StartDate,
DATEADD(DAY, -1, DATEADD(MONTH, n, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0))) AS EndDate
FROM CteMonths
) t
WHERE
sa.[Date] >= t.StartDate
AND sa.[Date] < DATEADD(DAY, 1, t.EndDate)
AND sa.AttendanceStatusId = 1
GROUP BY sa.StaffId
This is my stored procedure which I was able to create
CREATE PROCEDURE [dbo].[spGetAllStaffCollectiveAttendanceByMonth]
#Month nvarchar(9)
AS
BEGIN
Declare #StartDate DATE,
#EndDate DATE
;WITH CteMonths(n, m) AS(
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'April' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'June' UNION ALL
SELECT 7, 'July' UNION ALL
SELECT 8, 'August' UNION ALL
SELECT 9, 'September' UNION ALL
SELECT 10, 'October' UNION ALL
SELECT 11, 'November' UNION ALL
SELECT 12, 'December'
)
SELECT #StartDate = DATEADD(MONTH, n - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)),
#EndDate = DATEADD(DAY, -1, DATEADD(MONTH, n, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)))
FROM CteMonths
WHERE m = #month
SELECT
StaffAttendance.StaffId,
DATENAME(MONTH, #StartDate) AS [ForMonth], #StartDate AS StartDate, #EndDate AS EndDate,
(DATEDIFF(dd, #StartDate, #EndDate) + 1)-(DATEDIFF(wk, #StartDate, #EndDate) * 1)-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END) AS TotalWorkingDays,
SUM(StaffAttendance.AttendanceStatusId) AS TotalDaysWorked
FROM StaffAttendance
WHERE [Date] BETWEEN #StartDate AND #EndDate AND StaffAttendance.AttendanceStatusId = 1 GROUP BY StaffAttendance.StaffId
END
GO
This, here, is my function which I am trying to create but can't. Its the same thing as above except for what makes it a function.
CREATE FUNCTION [dbo].[funcGetAllStaffCollectiveAttendanceByMonth]
(
#Month nvarchar(9)
)
RETURNS TABLE
AS
RETURN
(
Declare #StartDate DATE,
#EndDate DATE
;WITH CteMonths(n, m) AS(
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'April' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'June' UNION ALL
SELECT 7, 'July' UNION ALL
SELECT 8, 'August' UNION ALL
SELECT 9, 'September' UNION ALL
SELECT 10, 'October' UNION ALL
SELECT 11, 'November' UNION ALL
SELECT 12, 'December'
)
SELECT #StartDate = DATEADD(MONTH, n - 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)),
#EndDate = DATEADD(DAY, -1, DATEADD(MONTH, n, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)))
FROM CteMonths
WHERE m = #month
SELECT
StaffAttendance.StaffId,
DATENAME(MONTH, #StartDate) AS [ForMonth], #StartDate AS StartDate, #EndDate AS EndDate,
(DATEDIFF(dd, #StartDate, #EndDate) + 1)-(DATEDIFF(wk, #StartDate, #EndDate) * 1)-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END) AS TotalWorkingDays,
SUM(StaffAttendance.AttendanceStatusId) AS TotalDaysWorked
FROM StaffAttendance
WHERE [Date] BETWEEN #StartDate AND #EndDate AND StaffAttendance.AttendanceStatusId = 1 GROUP BY StaffAttendance.StaffId
END
)
But this is what I am getting
What am I doing wrong?
You have used the syntax for an inline table-valued function but you have multiple statements.
Comparison of inline and multi-statement table-valued functions.
So you could either refactor to use a single statement (higher performance) or use the multi-statement syntax as described in that link (easier).
If you wanted to do it inline you could do something along these lines (note, I don't have SSMS available right now so there may be some minor syntax errors like unmatched brackets):
CREATE FUNCTION [dbo].[funcGetAllStaffCollectiveAttendanceByMonth]
(
#Month nvarchar(9)
)
RETURNS TABLE
AS
RETURN
(
-- The StartDate should be the first day of the month that is passed as a parameter, in the current year.
-- The EndDate should be the last day of the month which the StartDate begins.
WITH cteDates AS (
SELECT StartDate = Convert(date, Concat('01', #Month, Convert(varchar(4), DatePart(Year, GetDate()))), 106),
EndDate = DateAdd(Day, -1,
DateAdd(Month, 1,
Convert(date, Concat('01', #Month, Convert(varchar(4), DatePart(Year, GetDate()))) , 106)
)
)
)
SELECT
Sa.StaffId,
DATENAME(MONTH, cteDates.StartDate) AS [ForMonth],
cteDates.StartDate,
cteDates.EndDate,
(DATEDIFF(dd, cteDates.StartDate, cteDates.EndDate) + 1)-
(DATEDIFF(wk, cteDates.StartDate, cteDates.EndDate) * 1)-
(CASE WHEN DATENAME(dw, cteDates.StartDate) = 'Sunday' THEN 1 ELSE 0 END) AS TotalWorkingDays,
SUM(sa.AttendanceStatusId) AS TotalDaysWorked
FROM StaffAttendance As sa
JOIN cteDates ON sa.[Date] BETWEEN cteDates.StartDate AND cteDates.EndDate
WHERE sa.AttendanceStatusId = 1
GROUP BY
Sa.StaffId,
DATENAME(MONTH, cteDates.StartDate),
cteDates.StartDate,
cteDates.EndDate,
(DATEDIFF(dd, cteDates.StartDate, cteDates.EndDate) + 1)-
(DATEDIFF(wk, cteDates.StartDate, cteDates.EndDate) * 1)-
(CASE WHEN DATENAME(dw, cteDates.StartDate) = 'Sunday' THEN 1 ELSE 0 END)
END
)
SELECT *
FROM TABLE TB
WHERE TB.DATE >= dateadd(day, 1-datepart(dw, getdate()), CONVERT(date,getdate()))
AND TB.DATE < dateadd(day, 8-datepart(dw, getdate()), CONVERT(date,getdate()))
My dates look like this: 2015-01-19 00:00:00
Currently my query returns no records. I want to return records from this week. Anything created from Monday to Sunday.
I am using SQL Server 10.50.1617
Try this, it will find all data from this week from monday to sunday:
SELECT *
FROM TABLE TB
WHERE
TB.DATE >= dateadd(d, 0, datediff(d, 0, current_timestamp)/7*7)
AND TB.DATE < dateadd(d, 7, datediff(d, 0, current_timestamp)/7*7)
This will work for current week Monday - Sunday:
SELECT *
FROM TABLE TB
WHERE TB.DATE >= (DATEADD(day, DATEDIFF(day, 1, getdate()) / 7 * 7, - 0))
AND TB.DATE <= DATEADD(dd,DATEDIFF(dd,0,getdate())+ 1 , + 2)
This will get you prior week Monday - Sunday:
SELECT *
FROM TABLE TB
WHERE TB.DATE >= DATEADD(wk, DATEDIFF(wk, 6, GETDATE())-1, 7)
AND TB.DATE <= (DATEADD(day, DATEDIFF(day, 1, getdate()) / 7 * 7, - 1))