Get Quarter and Year between two dates - sql

I'd like to retrieve the list of years and quarters between two dates.
For example, from 25/12/2015 to 06/30/2017, the result should look like:
Year Quarter
2015 4
2016 1
2016 2
2016 3
2016 4
2017 1
2017 2
2017 3

You can use a tally table to do this.
declare #start date='2015-12-25';
declare #end date = '2017-06-30';
select distinct year(dateadd(day,rnum,#start)) yr,
datepart(quarter,dateadd(day,rnum,#start)) qtr
from (select row_number() over(order by (select null)) as rnum
from master..spt_values) t
where dateadd(day,rnum,#start) <= #end;

If you need to span more than 6 years... virtually identical to vkp (he's so fast!)
Declare #Date1 date = '2015-12-25'
Declare #Date2 date = '2017-06-30'
Select Distinct
[Year] =DatePart(YEAR,D)
,[Quarter]=DatePart(QUARTER,D)
From (
Select Top (DateDiff(DD,#Date1,#Date2)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),#Date1)
From master..spt_values n1,master..spt_values n2
) A
Returns
Year Quarter
2015 4
2016 1
2016 2
2016 3
2016 4
2017 1
2017 2

Declare #StartDate Date='2016-01-01'
, #EndDate Date='2017-05-01'
DECLARE #Date TABLE
(
[Year] INT,
[Quarter] INT
)
WHILE #StartDate <= #EndDate
BEGIN
INSERT INTO #Date
([Year],
[Quarter])
SELECT DATEPART(YEAR,#StartDate) AS [Year],
CASE WHEN DATEPART(MM,#StartDate) BETWEEN 1 AND 3 THEN 1
WHEN DATEPART(MM,#StartDate) BETWEEN 4 AND 6 THEN 2
WHEN DATEPART(MM,#StartDate) BETWEEN 7 AND 9 THEN 3
WHEN DATEPART(MM,#StartDate) BETWEEN 10 AND 12 THEN 4
END AS [Quarter]
SET #StartDate = DATEADD(DAY,1,#StartDate)
END
SELECT DISTINCT [Year],[Quarter] FROM #Date

Related

Building a table of year and quarter combinations

Say I have a year and a quarter and I want to build a table lists a specific number of year and quarter combinations ending with the given year and quarter.
E.g.
**Input:**
Year = 2018
Quarter = 3
NumRows = 4
**Output:**
Year.....|Quarter
2018.....|3
2018.....|2
2018.....|1
2017.....|4
You can use recursive generation.
First you need to build a DATETIME object from the year and quarter.
DECLARE #Quarter INT = 3;
DECLARE #Year INT = 2018;
DECLARE #NumRows INT = 4;
DECLARE #initial_date DATETIME = DATEADD(quarter, #Quarter-1, DATEADD(year, #Year-1900, 0));
Then you can recursively generate the year & quarter combinations like this.
;WITH quarters AS (
SELECT #initial_date AS [qdate]
UNION ALL
SELECT DATEADD(quarter, -1, [qdate]) AS [qdate]
FROM quarters
WHERE [qdate] > DATEADD(quarter, -1*(#NumRows-1), #initial_date)
)
SELECT DATEPART(year, qdate) as year, DATEPART(quarter, qdate) as quarter FROM quarters
this uses a recursive cte
for
declare #year int = 2018,
#quarter int = 3,
#numrows int = 6
; with rcte as
(
select n = 1,
yr = #year,
qtr = #quarter
union all
select n = n + 1,
yr = yr - (((qtr - 1 + 4 - 1) % 4 + 1) / 4),
qtr = (qtr - 1 + 4 - 1) % 4 + 1
from rcte
where n < #numrows
)
select *
from rcte
order by n
/* result:
n yr qtr
1 2018 3
2 2018 2
3 2018 1
4 2017 4
5 2017 3
6 2017 2
*/
You can try to use cte recursive with some calculation
DECLARE #Year INT= 2018
DECLARE #Quarter INT = 3
DECLARE #NumRows INT= 10
;WITH CTE AS (
SELECT (#Year - #NumRows/4) yr,
4 - (#NumRows % 4) Quarter,
#NumRows NumRows
UNION ALL
SELECT yr + Quarter / 4,
CASE WHEN (Quarter + 1) % 4 = 0 THEN 4
ELSE (Quarter + 1) % 4
END,
NumRows- 1
FROM CTE
WHERE NumRows > 1
)
select yr,Quarter
from cte
sqlfiddle

SQL: add missing months from different years

SQL SERVER
[CreatedOn] - DATETIME
I get this table:
Year Month Count
2009 7 1
2009 9 1
2010 1 2
2010 3 13
From query:
SELECT
YEAR ([CreatedOn]) AS 'Year',
MONTH ([CreatedOn]) AS 'Month',
COUNT ([CreatedOn]) AS 'Count'
FROM xxx
GROUP BY YEAR ([CreatedOn]), MONTH ([CreatedOn])
How can I get table like this (with missed months and Count 0):
Year Month Count
2009 7 1
2009 8 0
2009 9 1
2009 10 0
2009 11 0
2009 12 0
2010 1 2
2010 2 0
2010 3 13
Syntax says you are using MSSQL. Use Recursive CTE to generate the calender table then do a Left outer join with XXX table
DECLARE #maxdate DATE = (SELECT Max([CreatedOn])
FROM xxx);
WITH calender
AS (SELECT Min([CreatedOn]) dates,
FROM xxx
UNION ALL
SELECT Dateadd(mm, 1, dates)
FROM cte
WHERE dates < #maxdate)
SELECT Year(dates) [YEAR],
Month(dates) [month],
Count ([CreatedOn]) AS 'Count'
FROM calender a
LEFT OUTER JOIN xxx b
ON Year(dates) = Year ([CreatedOn])
AND Month(dates) = Month ([CreatedOn])
GROUP BY Year(dates),
Month(dates)
Note : Instead of Recursive CTE create a physical calender table
This will use a build in table to create the calendar:
;WITH limits as
(
SELECT min([CreatedOn]) mi, max([CreatedOn]) ma
FROM xxx
), months as(
SELECT
dateadd(mm, number, mi) m
FROM
master..spt_values v
JOIN
limits l
ON
number between 0 and datediff(mm, l.mi, l.ma)
WHERE
v.type = 'P'
)
SELECT
year(months.m) year,
month(months.m) month,
count(qry.[CreatedOn]) cnt
FROM
xxx qry
RIGHT JOIN
months
ON
months.m = dateadd(mm, datediff(mm, 0, qry.[CreatedOn]), 0)
GROUP BY
year(months.m),
month(months.m)

how to get the month and year value for the give financial year

how to get the month and year value for the give financial year
if my input is 2013.
my expected out put is
Month Year
4 2013
5 2013
6 2013
7 2013
8 2013
9 2013
10 2013
11 2013
12 2013
1 2014
2 2014
3 2014
Use Recursive CTE to get the expected result.
DECLARE #nYearInput AS CHAR(4)
DECLARE #start DATETIME, #end DATETIME
SET #nYearInput = '2013' -- Change your input here
SET #start = CAST(#nYearInput AS VARCHAR) + '0401'
SET #end= CAST(#nYearInput + 1 AS VARCHAR) + '0301'
;WITH cte AS
(
SELECT dt = DATEADD(DAY, -(DAY(#start) - 1), #start)
UNION ALL
SELECT DATEADD(MONTH, 1, dt)
FROM cte
WHERE dt < DATEADD(DAY, -(DAY(#end) - 1), #end)
)
SELECT YEAR(dt) AS Year, month(dt) AS month
FROM cte

SQL - Create a temp table or CTE of first day of the month and month names

I need to create a temp table or common table expression based on 2 paremters in a SQL Server 2012 environment
#calYear
#currentYear
so if #calYear = 5 and #currentYear='2014'
I would like to generate a temp table of 5 years starting from current year with 4 columns like
YearDesc MonthName MonthNum FirstDayOfMonth
2014 Jan 1 1/1/2014
2014 Feb 2 2/1/2014
2014 Mar 3 3/1/2014
...
...
...
2018 Oct 10 10/1/2018
2018 Nov 11 11/1/2018
2018 Dec 12 12/1/2018
Is it possible to do a Do While loop efficently? How would I account for the month names?
I'm using a really cumbersome Do While loop to iterate all the months of the year then iterate all the years.
One way using a recursive cte:
declare #calYear int = 5, #currentYear char(4) = '2014'
;with cte (dt) as (
select DATEFROMPARTS(#currentyear,1,1) dt
union all
select dateadd(month,1,dt)
from cte where dt < dateadd(year,#calyear,DATEFROMPARTS(#currentyear,1,1))
)
select year(dt) YearDesc, datename(month, dt) MonthName, month(dt) MonthNum, dt FirstDayOfMonth
from cte
order by dt
Or using a numbers table: (in this case master..spt_values)
declare #calYear int = 5, #currentYear char(4) = '2014'
;with cte2 (dt) as (
select dateadd(month,number,DATEFROMPARTS(#currentyear,1,1)) dt
from master..spt_values where type = 'p'
and number <= 12*#calYear
)
select year(dt) YearDesc, datename(month, dt) MonthName, month(dt) MonthNum, dt FirstDayOfMonth
from cte2
order by dt

Is it possible to display months between two dates in sql using a single select statement without using temp tables [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Months between two dates
I have date range as [start date] = '2012-09-01' and [finish date] = '2014-01-01'
Now, I need to display months between two dates..using a single select statement
Expected Output :
9
10
11
12
1
2
3
.
.
.
12
1
How can I do this?
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = '20120901'
,#EndDate = '20140101';
;WITH MONTHS (date)
AS
(
SELECT #StartDate
UNION ALL
SELECT DATEADD(MONTH,1,date)
FROM MONTHS
WHERE DATEADD(MONTH,1,date)<=#EndDate
)
SELECT MONTH(date) AS MONTH FROM MONTHS
Result:
MONTH
-----------
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
1
(17 row(s) affected)
EDIT:
As per your updated requirement you can achieve this using following query:
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = '20120901'
,#EndDate = '20140101';
SELECT MONTH(DATEADD(MONTH, x.number, #StartDate)) AS Months
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate);
Result:
Months
-----------
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
1
(17 row(s) affected)
You can user table variables also:
DECLARE #startdt DATETIME, #enddt DATETIME
SELECT #startdt = '2012-09-01', #enddt = '2014-01-01'
DECLARE #Months TABLE (Months INT)
INSERT INTO #Months VALUES (MONTH(#startdt))
WHILE #startdt < #enddt
BEGIN
SET #startdt = DATEADD(MONTH,1,#startdt)
INSERT INTO #Months VALUES (MONTH(#startdt))
END
SELECT * FROM #Months