An SQL query to show the last BUSINESS day of the month - sql

Here is my query:
CREATE FUNCTION dbo.ufn_LastBusinessDayOfMonth (#Dt datetime)
RETURNS datetime
AS
BEGIN
DECLARE #dt2 datetime
DECLARE #Df int
DECLARE #dSat int
DECLARE #dSun int
SELECT
#dt2 = DATEADD(D, -1, DATEADD(m, 1 + DATEDIFF(m, 0, #Dt), 0))
SELECT
#dSat = DATEPART(dw, '2018-01-06') -- Known Saturday
SELECT
#dSun = (#dSat % 7) + 1
SELECT
#dt2 = (
CASE
WHEN DATEPART(dw, #dt2) = #dSun THEN DATEADD(DAY, -2, #dt2)
WHEN DATEPART(dw, #dt2) = #dSat THEN DATEADD(DAY, -1, #dt2)
ELSE #dt2
END)
RETURN #dt2
END

DECLARE #Dt datetime
SET #Dt = '03/21/2018'
DECLARE #lastOfMonth datetime, #3DaysBeforeTheEnd DATETIME
set #lastOfMonth = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#Dt)+1,0))
SET #3DaysBeforeTheEnd = DATEADD(d,-2,#lastOfMonth)
select top 1 DATENAME(weekday, x.[Date]), x.[Date]
from (
SELECT TOP (DATEDIFF(DAY, #3DaysBeforeTheEnd, #lastOfMonth) + 1)
[Date] = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, #3DaysBeforeTheEnd)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
)x
WHERE DATENAME(weekday, x.[Date]) NOT IN ('Saturday','sunday')
order by x.[Date] desc

Related

Fill in the date gaps from the stuff

I have this result, [year.month week] with my query below
[2021.12 51],[2021.12 53],[2022.01 1],[2022.01 2],[2022.01 3],[2022.01 5],[2022.01 6],[2022.02 10]
My goal is to fill in the gaps of the week, for example:
[2021.12 51],**[2021.12 52]**,[2021.12 53],[2022.01 1],[2022.01 2],[2022.01 3],**[2022.01 4]**,[2022.01 5],[2022.01 6],**[2022.01 7]**,**[2022.01 8]**,**[2022.01 9]**,[2022.02 10]
How could I do this with my query below:
DECLARE
#startdate datetime,
#enddate datetime,
#paramdef nvarchar(max)
set #startdate = '2021-01-01 00:00:00.000';
set #enddate = GETDATE();
set #paramdef = '#startdate datetime, #enddate datetime';
SELECT STUFF
(
(
SELECT
',' + QUOTENAME( S_FORMATTED_WEEK_MONTH )
FROM
MONITORING
WHERE
S_DATE_TO >= #startdate AND
S_DATE_TO <= #enddate
GROUP BY
S_FORMATTED_WEEK_MONTH
ORDER BY
CAST( REPLACE( SUBSTRING(S_FORMATTED_WEEK_MONTH, 1, 7), '.', '' ) AS INT ),
CAST( REPLACE( SUBSTRING(S_FORMATTED_WEEK_MONTH, 8, 9), '.', '' ) AS INT )
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') ,1,1,''
)
you can use the below calendar table approach to get the list of weeknumbers as per your format.
DECLARE #StartDate DATE = '2021-01-01'
DECLARE #EndDate DATE = getdate()
;WITH Cal(n) AS
(
SELECT 0 UNION ALL SELECT n + 1 FROM Cal
WHERE n < DATEDIFF(DAY, #StartDate, #EndDate)
),
FnlDt(d,y,m,w) AS
(
SELECT DATEADD(DAY, n, #StartDate)
, year(DATEADD(DAY, n, #StartDate))
, month(DATEADD(DAY, n, #StartDate))
, datepart(week,DATEADD(DAY, n, #StartDate)) FROM Cal
)
select
string_agg(weekarr,',') as concat_weekarr
from
(SELECT concat('[',y,'.',m,' ',w,']') as weekarr
FROM fnlDt
group by y,m,w
) as dt
option(maxrecursion 32767)
[2021.1 1],[2021.1 2],[2021.1 3],[2021.1 4],...

Convert a string to date in SQL Server

I am facing a problem where I need to convert a string to date like
11 years 10 months 12 days to a date in SQL Server.
Please help any help would be appreciated.
I guess you want something like this
DECLARE #str VARCHAR(50)= '1 year 12 months 2 days'
DECLARE #days INT= LEFT(#str, Charindex(' ', #str)),
#months INT = Substring(#str, Charindex('months', #str) - 3, 2),
#years INT = Substring(#str, Charindex('days', #str) - 3, 2);
WITH days_back
AS (SELECT Dateadd(day, -#days, Cast(Getdate() AS DATE)) AS day_date),
month_back
AS (SELECT Dateadd(month, -#months, day_date) AS month_date
FROM days_back)
SELECT Result = Dateadd(year, -#years, month_date)
FROM month_back
declare #fuzzy_date varchar(255) = '11 years 10 months 12 days'
declare #date date
declare #startdate date = '1999-12-31'
declare #today_to_before date = getdate()
declare #today_to_after date = getdate()
declare #years int, #months int, #days int, #foo varchar(255)
Set #years = left(#fuzzy_date, charindex('years', #fuzzy_date) - 1)
Select #fuzzy_date = right(#fuzzy_date, len(#fuzzy_date) - charindex('years', #fuzzy_date) - 5)
select #months = left(#fuzzy_date, charindex('months', #fuzzy_date) - 1)
Select #days = replace(right(#fuzzy_date, len(#fuzzy_date) - charindex('months', #fuzzy_date) - 6), 'days', '')
Select #years, #months, #days
Set #date = dateadd(yy, #years, #startdate)
Set #date = dateadd(mm, #months, #date)
Set #date = dateadd(dd, #days, #date)
Set #today_to_after = dateadd(yy, #years, #today_to_after)
Set #today_to_after = dateadd(mm, #months, #today_to_after)
Set #today_to_after = dateadd(dd, #days, #today_to_after)
Set #today_to_before = dateadd(yy, -#years, #today_to_before)
Set #today_to_before = dateadd(mm, -#months, #today_to_before)
Set #today_to_before = dateadd(dd, -#days, #today_to_before)
Select #date,#today_to_after,#today_to_before

Find the Same day of Previous Year Given by Current Year Date in SQL Server

I am working with SQL Server, The scenario is to find out the Same Day's Date of Previous Year as of Today's Day.
Suppose 2014-03-06 is Today Date and Day is Thursday I want to Find the Same day in Previous lies in the same week .which is 2013-03-07
can any body help?
HERE is what i Have Written:
DECLARE #DateFrom AS DATETIME
DECLARE #DateTo AS DATETIME
SET #DateFrom = '2014-01-01'
SET #DateTo = '2014-02-10'
DECLARE #Count AS INT
SET #Count = DATEDIFF(DAY, #DateFrom, #DateTo)
CREATE TABLE #current_year /*This Year*/
(
[Date] DATETIME ,
WeekNum INT,
[Day] VARCHAR(20),
Data INT
)
CREATE TABLE #last_year /*This Year -1*/
(
[Date] DATETIME ,
WeekNum INT,
[Day] VARCHAR(20),
Data INT
)
WHILE ( #Count > 0 )
BEGIN
INSERT INTO #current_year
VALUES ( CONVERT(VARCHAR(10), #DateFrom, 101),
DATEPART(week,#DateFrom),
DATENAME(weekday, #DateFrom),#Count)
INSERT INTO #last_year
VALUES ( CONVERT(VARCHAR(10), DATEADD(YEAR, -1, #DateFrom), 101),
DATEPART(week,DATEADD(YEAR,1,#DateFrom)),
DATENAME(weekday, DATEADD(YEAR, -1, #DateFrom)),#Count)
SET #DateFrom = DATEADD(day, 1, #DateFrom)
SET #Count = #Count - 1
END
SELECT * from #current_year
SELECT * from #last_year
SELECT CONVERT(varchar(10),#current_year.[Date],111) AS CYDate,
--ISNULL(CONVERT(varchar(10),#last_year.[Date],111) ,/*CONVERT(varchar(10),DateAdd(dd, 1, DATEADD(yy, -1, #current_year.Date)),111)*/) AS LYDate
--CONVERT(varchar(10),#last_year.[Date],111) AS LYDate
Coalesce(CONVERT(varchar(10),#last_year.[Date],111) ,DateAdd(dd, 1, DATEADD(yy, -1, #current_year.Date))) AS LYDate,
#current_year.Data AS CD,
#last_year.Data AS LD
FROM #current_year
--LEFT JOIN #last_year ON #last_year.WeekNum = #current_year.WeekNum
-- AND #last_year.[Day] = #current_year.[Day]
Left JOIN #last_year ON #last_year.WeekNum = DatePart(wk, GETDATE())
DROP TABLE #current_year
DROP TABLE #last_year
Here is the Output:
Here is the output after adding your solution, now in left join it excludes (NULL) data of previous year
Basically you need to find difference in days between same dates in this and previous years, then understand "day difference" by mod 7, and sum it with date in previous year:
DECLARE #now DATETIME
SET #now = '2014-03-06'
SELECT CAST (DATEADD(YEAR, -1, #now) + (CAST (#now as INT) - CAST (DATEADD(YEAR, -1, #now) AS INT)) % 7 AS DATE)
Returns
2013-03-07
Try
DECLARE #now Date
SET #now = '2014-06-03'
SELECT DATEADD(week, -52, #now)
SELECT DateName(dw, DATEADD(yy, -1, GETDATE()))
gives Wednesday
SELECT DateName(dw, DateAdd(dd, 1, DATEADD(yy, -1, GETDATE())))
gives Thursday
edit:
SELECT DateAdd(dd, 1, DATEADD(yy, -1, GETDATE()))
gives '2013-03-07 17:30:16.590'
you need to cast the date as per you requirement..
update:
change this part with,
Left JOIN #last_year ON #last_year.WeekNum = DatePart(wk, GETDATE())
in your case:
Left JOIN #last_year ON DatePart(wk, #last_year.[Date]) = DatePart(wk, #current_year.[Date])
update 2:
Left JOIN #last_year ON (MONTH(#last_year.[Date])=MONTH(#current_year.[Date]) and Day(#last_year.[Date])=Day(#current_year.[Date]))
Output:
or
output:
Left JOIN #last_year ON (#last_year.WeekNum = #current_year.WeekNum and #last_year.[Day] = #current_year.[Day])
choose which ever is your required output.
DECLARE #Date DATE = '2014-03-06'
SELECT DATEADD(WEEK,-52,#Date)
Retrun value :
2013-03-07

Returns date range by quarter?

I am looking for a query that can returns a series of date range that is one quarter long.
For example, if the input is 2/1/2013 and 3/31/2014, then the output would look like:
start end
2/1/2013 4/30/2013
5/1/2013 7/31/2013
8/1/2013 10/31/2013
11/1/2013 1/31/2014
2/1/2014 3/31/2014
Notice that the last quarter is only 2 months long. Thanks for help in advance.
Just want to add that this is what I did after I did a bit of googling. I was thinking of some more efficient way but I think this is sufficient for my purpose. The first part is to populate a date table, the second part to calculate the quarter range.
DECLARE #StartDate SMALLDATETIME
DECLARE #EndDate SMALLDATETIME
SET #StartDate = '1/1/2011'
SET #EndDate = '12/31/2011'
-- creates a date table, not needed if there is one already
DECLARE #date TABLE ( [date] SMALLDATETIME )
DECLARE #offset INT
SET #offset = 0
WHILE ( #offset < DATEDIFF(dd, #StartDate, DATEADD(dd, 1, #EndDate)) )
BEGIN
INSERT INTO #date ( [date] )
VALUES ( DATEADD(dd, #offset, #StartDate) )
SELECT #offset = #offset + 1
END ;
WITH dateCTE
AS ( SELECT ROW_NUMBER() OVER ( ORDER BY [date] ASC ) AS qID ,
[date] AS qStart ,
CASE WHEN DATEADD(dd, -1, DATEADD(q, 1, [date])) > #EndDate
THEN #EndDate
ELSE DATEADD(dd, -1, DATEADD(q, 1, [date]))
END AS qEnd
FROM #date
WHERE [date] = #StartDate
OR ( DATEDIFF(mm, #StartDate, [date]) % 3 = 0
AND DATEPART(dd, [date]) = DATEPART(dd,
#StartDate)
)
)

How to split date ranges based on months in SQL Server 2005

Ex: date range is 01-01-2011 to 01-01-2012, I want the output like this :
01-01-2011 31-01-2011
01-02-2011 28-02-2011
How can I do this ? I'm using SQL Server 2005..
Thanks
Using CTE:
DECLARE #Begin DATETIME
DECLARE #End DATETIME
SELECT #Begin = '20110101', #End = '20120101'
;WITH ranges(DateFrom, DateTo) AS
(
SELECT #Begin, DATEADD(DAY, -1, DATEADD(MONTH, 1, #begin))
UNION ALL
SELECT DATEADD(month, 1, DateFrom), DATEADD(DAY, -1, DATEADD(MONTH, 2, DateFrom))
FROM ranges
WHERE DateFrom < #End
)
SELECT * FROM ranges
OPTION(MAXRECURSION 0)
And not using CTE:
DECLARE #Begin DATETIME
DECLARE #End DATETIME
SELECT #Begin = '20110101', #End = '20120101'
SELECT DATEADD(MONTH, n.Number, #Begin) DateFrom, DATEADD(day, -1, DATEADD(MONTH, n.Number+1, #Begin)) DateTo
FROM master.dbo.spt_values n
WHERE
n.Number < DATEDIFF(MONTH, #begin, #end)
AND n.Type = 'P'
If you need to include January 2012 too, use this
DECLARE #Begin DATETIME
DECLARE #End DATETIME
SELECT #Begin = '20110101', #End = '20120101'
SELECT DATEADD(MONTH, n.Number, #Begin) DateFrom, DATEADD(day, -1, DATEADD(MONTH, n.Number+1, #Begin)) DateTo
FROM master.dbo.spt_values n
WHERE
n.Number <= DATEDIFF(MONTH, #begin, #end)
AND n.Type = 'P'
And CTE:
DECLARE #Begin DATETIME
DECLARE #End DATETIME
SELECT #Begin = '20110101', #End = '20120101'
;WITH ranges(DateFrom, DateTo) AS
(
SELECT #Begin, DATEADD(DAY, -1, DATEADD(MONTH, 1, #begin))
UNION ALL
SELECT DATEADD(month, 1, DateFrom), DATEADD(DAY, -1, DATEADD(MONTH, 2, DateFrom))
FROM ranges
WHERE DATEADD(month, 1, DateFrom) < #End
)
SELECT * FROM ranges
OPTION(MAXRECURSION 0)
>On Providing the Start and End Date range, it can be split into months. This might help.
DECLARE #StartDate datetime
DECLARE #EndDate datetime
DECLARE #tmpStart datetime
DECLARE #tmpEnd datetime
Select #StartDate = '2012-01-01'
Select #EndDate = '2009-01-01'
Select #StartDate = DATEADD(MONTH,1,Convert(DATETIME,Convert(VARCHAR(25), Datepart (YEAR,#StartDate)) + '-' + Convert(VARCHAR(25), Datepart(MONTH, #StartDate)) + '-' + Convert(VARCHAR(25), 1)))
Select #EndDate = DATEADD(MONTH,1,Convert(DATETIME,Convert(VARCHAR(25), Datepart(YEAR, #EndDate)) + '-' + Convert(VARCHAR(25), Datepart(MONTH, #EndDate)) + '-' + Convert(VARCHAR(25), 1)))
Select #EndDate = DATEADD(DD,-1, DATEADD(MM,1,#EndDate))
Select #tmpEnd = #EndDate
Select #tmpStart = Convert(DATETIME,Convert(VARCHAR(25), Datepart(YEAR, #tmpEnd)) + '-' +
Convert(VARCHAR(25), Datepart(MONTH, #tmpEnd)) + '-' + Convert(VARCHAR(25), 1))
Select #StartDate 'Start' , #EndDate 'End'
While #tmpStart <= #StartDate
BEGIN
Select #tmpStart 'tmpStart' , #tmpEnd 'tmpEnd'
Select #tmpStart = DATEADD(MM,1,#tmpStart)
Select #tmpEnd = DATEADD(DD,-1,DATEADD (MM, 1 , #tmpStart))
END