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

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

Related

Rows to one column

i have sql query:
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
,#EndDate = getdate();
SELECT LEFT(CONVERT(varchar, DATEADD(MM, DATEDIFF(MM, 0, DATEADD(MONTH, x.number, #StartDate)), 0),112),6) AS MonthName --LEFT(CONVERT(varchar, DATEADD(MONTH, x.number, #StartDate)), 0),112),6)
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate)`
i need to do it in this format:
201901, 201902
Thanks
For the older version of SQL Server, you can try like following.
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
,#EndDate = getdate();
;with cte as
(
SELECT LEFT(CONVERT(varchar, DATEADD(MM, DATEDIFF(MM, 0, DATEADD(MONTH, x.number, #StartDate)), 0),112),6) AS MonthName
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate)
)
SELECT DISTINCT
STUFF ((
SELECT ', ' + [MonthName]
FROM
cte
ORDER BY [MonthName]
FOR XML PATH('')
),1,2,'' )
AS [MonthName]
For SQL Server 2017+, you can use STRING_AGG like following.
select STRING_AGG (MonthName, ',') as MonthName
FROM CTE
Try this below query:
Select (Stuff((Select ', ' + cast(eid as varchar(10)) From employee FOR XML PATH('')),1,2,''))

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

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

Date Parameter sql

Im looking to write a function which declares a variable #StartDate to be the first of January but the year to be the year that you run the script(current year) which means the year can change but the day and month cant.
Anyone know how to do this ?
Example code:
IF #DATE_TYPE = 'FIRST QUARTER'
BEGIN
SET #START_DATE = 01/01/'Current Year'
SET #END_DATE = 31/03/'Current Year'
END
For SQL 2012 and above versions,
SELECT DATEFROMPARTS (YEAR(GETDATE()), 1, 1)
SELECT DATEFROMPARTS (YEAR(GETDATE()), 03, 31)
For All versions,
SELECT CAST('01 JAN '+CAST(DATEPART(YY,GETDATE()) AS NVARCHAR) AS DATETIME)
SELECT CAST('31 MAR '+CAST(DATEPART(YY,GETDATE()) AS NVARCHAR) AS DATETIME)
I think you can do something like this (it's better to use convert() when you define dates and not implicit conversion):
SET #START_DATE = CONVERT(datetime, CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '0101', 112)
SET #END_DATE = CONVERT(datetime, CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '0331', 112)
If youre using SQLSERVER 2012, you can use DATEFROMPARTS
DECLARE #START_DATE DATE,
#END_DATE DATE
SELECT #START_DATE = DATEFROMPARTS(YEAR(GETDATE()), 1, 1) ,
#END_DATE = DATEFROMPARTS(YEAR(GETDATE()), 03, 31)
SELECT #START_DATE [start_date] ,
#END_DATE [end_date]
Result:
start_date end_date
---------- ----------
2017-01-01 2017-03-31
(1 row(s) affected)
DECLARE #Day VARCHAR(10) = '1stQUARTER' --Give the quarter name condiations like 1stQUARTER,2ndQUARTER,3rdQUARTER,4thQuarter
IF (#Day = '1stQUARTER')
BEGIN
SELECT CASE
WHEN DATENAME(QUARTER, getdate()) - 1 = 1
THEN DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) - 1, 0)
END AS StartDayQuarter
,CASE
WHEN DATENAME(QUARTER, getdate()) - 1 = 1
THEN DATEADD(dd, - 1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0))
END AS EndDayQuarter
END
ELSE IF (#Day = '2ndQUARTER')
BEGIN
SELECT CASE
WHEN DATENAME(QUARTER, getdate()) = 2
THEN DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)
END AS FirstDayQuarter
,CASE
WHEN DATENAME(QUARTER, getdate()) = 2
THEN DATEADD(mm, + 3, DATEADD(dd, - 1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)))
END AS LasttDayQuarter
END
ELSE IF (#Day = '3rdQUARTER')
BEGIN
SELECT CASE
WHEN DATENAME(QUARTER, getdate()) + 1 = 3
THEN DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) + 1, 0)
END AS FirstDayQuarter
,CASE
WHEN DATENAME(QUARTER, getdate()) + 1 = 3
THEN DATEADD(mm, + 6, DATEADD(dd, - 1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)))
END AS LasttDayQuarter
END
ELSE IF (#Day = '4thQuarter')
BEGIN
SELECT CASE
WHEN DATENAME(QUARTER, getdate()) + 2 = 4
THEN DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) + 2, 0)
END AS FirstDayQuarter
,CASE
WHEN DATENAME(QUARTER, getdate()) + 2 = 4
THEN DATEADD(mm, + 9, DATEADD(dd, - 1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)))
END AS LasttDayQuarter
END
ELSE
BEGIN
PRINT 'Enter Valid Quarter Name'
END
OutPut
FirstDayQuarter |LasttDayQuarter
--------------------------------------------
2017-01-01 00:00:00.000 |2017-03-31 00:00:00.000
In Sql 2012+, you could use Datefromparts
IF #DATE_TYPE = 'FIRST QUARTER'
BEGIN
SET #START_DATE = datefromparts(year(getdate()), 1,1)
SET #END_DATE = datefromparts(year(getdate()), 3,31)
END
If you want to get the fisrt date and the last date of a quarter, then use it
DECLARE #CurrentDate datetime = '2017-07-01' -- or getdate() or any date
SELECT datefromparts(year(#CurrentDate),
datepart(quarter, #CurrentDate) * 3 - 2,1) AS StartDate,
EOMONTH(datefromparts(year(#CurrentDate),
datepart(quarter, #CurrentDate) * 3 , 1)) AS EndDate
DECLARE #START_DATE DATETIME
DECLARE #END_DATE DATETIME
DECLARE #DATE_TYPE VARCHAR(500)
DECLARE #YEAR VARCHAR(4)
SET #DATE_TYPE = 'FIRST QUARTER' -- SAMPLE PARAMETER
SET #YEAR = CAST(YEAR(GETDATE()) AS VARCHAR(4))
DECLARE #tbl TABLE ([QUARTER] VARCHAR(50), StartMonth VARCHAR(2), EndMonth VARCHAR(2))
INSERT INTO #tbl ([QUARTER], StartMonth, EndMonth)
SELECT 'FIRST QUARTER', '1', '3'
UNION ALL
SELECT 'SECOND QUARTER', '4', '6'
UNION ALL
SELECT 'THIRD QUARTER', '7', '9'
UNION ALL
SELECT 'FOURTH QUARTER', '10', '12'
SELECT #START_DATE = StartMonth + '/1/' + #YEAR,
#END_DATE = DATEADD(DD, -1, (DATEADD(mm, 1, EndMonth + '/1/' + #YEAR)))
FROM #tbl
WHERE [QUARTER] = #DATE_TYPE

check is there any weekday inside time given sql server

I have been wondering is there any operator/function in sql server to tell about weekday between given day.
Example :11-19-2016 to 11-29-2016 I want check if there is tuesday between that day?
Try This:
declare #start varchar(100)='11-19-2016'
declare #end varchar(100)='11-29-2016'
;with dateRange as
(
select date = dateadd(dd, 1, #start)
where dateadd(dd, 1, #start) < #end
union all
select dateadd(dd, 1, date)
from dateRange
where dateadd(dd, 1, date) < #end
)
select date,DATENAME(dw,CAST(DATEPART(m, GETDATE()) AS VARCHAR)
+ '/'+ CAST(DATEPART(d, date) AS VARCHAR)
+ '/'+ CAST(DATEPART(yy, getdate()) AS VARCHAR)) as 'Day'
from dateRange where (DATENAME(dw,CAST(DATEPART(m, GETDATE()) AS VARCHAR)
+ '/'+ CAST(DATEPART(d, date) AS VARCHAR)
+ '/'+ CAST(DATEPART(yy, getdate()) AS VARCHAR)))='Tuesday'
The query below uses a recursive query to unfold the date range.
Then uses DATEPART to select only the Tuesdays from it.
But one could also use DATENAME instead.
declare #StartDate DATE = '2016-11-19';
declare #EndDate DATE = '2016-11-29';
--SET DATEFIRST 7;
-- The dw for tuesday is 3 when ##datefirst = 7 (default setting)
-- Since it depends on a usersetting, lets calculate it anyway.
declare #TuesdayWeekday INT = (7-##datefirst + 2)%7+1;
;with DATES as
(
select #startdate as [Date]
union all
select dateadd(day, 1, [Date]) from DATES
where [Date] < #enddate
)
select [Date], datepart(dw,[Date]) as day_of_week, datename(dw,[Date]) as day_of_weekname
from DATES
where datepart(dw,[Date]) = #TuesdayWeekday;

How can i find the particular days

I have the date value like this - 12/2011 or 11/2011 (MM/yyyy)
I want to find the sundays on the particular month....
For Example, If i select the month 01/2012, The query should give the result like this
01
08
15
22
29
The above date are sunday.
Expected Output for 01/2012 Month
01
08
15
22
29
How to make a query
Need Query Help
With a little help of a number table (master..spt_values)
declare #M varchar(7)
set #M = '01/2012'
declare #D datetime
set #D = convert(datetime, '01/'+#M, 103)
set datefirst 7
select dateadd(day, N.Number, #D)
from master..spt_values as N
where N.type = 'P' and
dateadd(day, N.Number, #D) >= #D and
dateadd(day, N.Number, #D) < dateadd(month, 1, #D) and
datepart(weekday, dateadd(day, N.Number, #D)) = 1
Here it comes:
SET DATEFIRST 1
DECLARE #givenMonth CHAR(7)
SET #givenMonth = '12/2011'
DECLARE #month INT
SET #month = CAST(SUBSTRING(#givenMonth, 1, 2) AS INT)
DECLARE #year INT
SET #year = CAST(SUBSTRING(#givenMonth, 4, 4) AS INT)
DECLARE #Date DATETIME
SET #Date = DATEADD(month, #month - 1, CAST(CAST(#year AS CHAR(4)) AS DATETIME))
DECLARE #nextMonth DATETIME
SET #nextMonth = DATEADD(MONTH, 1, #date)
DECLARE #firstSunday DATETIME
SET #firstSunday = DATEADD(day, 7 - DATEPART(weekday, #date), #date)
CREATE TABLE #Days(Sunday INT)
WHILE #firstSunday < #nextMonth
BEGIN
INSERT #Days
SELECT DATEPART(DAY, #firstSunday) Sunday
SET #firstSunday = DATEADD(day, 7, #firstSunday)
END
SELECT Sunday
FROM #Days
ORDER BY 1
DROP TABLE #Days
Edit: use a numbers table in place of the CTE because you are in SQL Server 2000. C'mon, upgrade and do yourself a favour
DECLARE #monthyear varchar(10) = '11/2012';
DECLARE #start smalldatetime, #end smalldatetime;
-- use yyyymmdd format
SET #start = CAST(RIGHT(#monthyear, 4)+ LEFT(#monthyear, 2) + '01' AS smalldatetime);
-- work backwards from start of next month
SET #end = DATEADD(day, -1, DATEADD(month, 1, #start));
-- recursive CTE. Would be easier with a numbers table
;WITH daycte AS
(
SELECT #start AS TheDay
UNION ALL
SELECT DATEADD(day, 1, TheDay)
FROM daycte
WHERE TheDay < #end
)
SELECT DATENAME(day, TheDay)
FROM daycte
-- One of many ways.
-- This is independent of ##datefirst but fails with Chinese and Japanese language settings
WHERE DATENAME(weekday, TheDay) = 'Sunday';
You can change date format and use DateName function.
SELECT DateName(dw, GETDATE())