Grouping Fiscal year using SQL Server - sql

Is there a way in SQL Server that can show the Fiscal Year (begins on October 1 and ends on September 30) from a table which has a date column (1998 to 2010). Here is what I have done:
select 'FY1999' as FY, site, count(*)
from mytable
where mydate >='10/1/1998'
and mydate <'10/1/1999'
group by site
select 'FY2000' as FY, site, count(*)
from mytable
where mydate >='10/1/1999'
and mydate <'10/1/2000'
group by site
select 'FY2001' as FY, site, count(*)
from mytable
where mydate >='10/1/2000'
and mydate <'10/1/2001'
group by site
Isn't it too much repetitive when doing this for more then 10 FY year?

Here's a single query that will give you the information you want.
SELECT DATEPART(yyyy, DATEADD(mm, 3, mydate)) AS FY, site, COUNT(*) AS row_count
FROM mytable
GROUP BY DATEPART(yyyy, DATEADD(mm, 3, mydate)), site

You can even create your user-defined function in SQL Server that takes a date argument and returns the fiscal year as an int:
CREATE FUNCTION GetFiscalYear(#TheDate date)
RETURNS int
AS
BEGIN
DECLARE #FiscalYear int
IF DATEPART(month, #TheDate) < 10
SELECT #FiscalYear = DATEPART(year, #TheDate)
ELSE
SELECT #FiscalYear = DATEPART(year, #TheDate) + 1
RETURN #FiscalYear
END
Then you can use this as, for example:
SELECT Id, ShippingDate, GetFiscalYear(ShippingDate)
FROM SomeTable

Yes, it is a bit repetitive. I'd be using DatePart and some easy to discern rules:
Fiscal year is the year of the date if the month is < 10.
Fiscal year is the year of the date + 1 if the month >= 10

This is the dynamic script for UK, April to March,
for different dates you can use as refernece,
Good Luck
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = DATEADD(dd,0, DATEDIFF(dd,0, DATEADD( mm, -(((12 + DATEPART(m, getDate())) - 4)%12), getDate() ) - datePart(d,DATEADD( mm, -(((12 + DATEPART(m, getDate())) - 4)%12),getDate() ))+1 ) )
SET #EndDate = DATEADD(SS,-1,DATEADD(mm,12,#StartDate))
SELECT #StartDate,#EndDate

Start of fiscal year:
DATEADD(MONTH, DATEDIFF(MONTH, '20100401', getdate()) / 12 * 12, '20100401')
End of Fiscal Year
DATEADD(MONTH, DATEDIFF(MONTH, '20100401', getdate()) / 12 * 12, '20110331')
Replace getdate() with your own date if required

I don't have a SQL server reference handy, but here's how I'd do it in MySQL:
select date_format (date_add(mydate, interval 92 days), 'FY%Y') as FY, site, count(*)
from mytable
group by FY, site;
There are 92 days in October, November, and December, so I've offset by that much.

Yesterday there was an answer to this question, which was subsequently deleted.
I do not know why. Was there something wrong with it?
Please don't vote this answer down, I just want to know why it was deleted.
With vigorous testing, I still can't manage to fault it. In my example, Fiscal year starts July 1.
The answer was:
SELECT SUM(value), CAST(Year(DateAdd(Month, -6, TransactionDate)) as varchar) + ' - ' + CAST(Year(DateAdd(Month, 6, TransactionDate)) as varchar) as 'FY'
FROM mytable
GROUP BY CAST(Year(DateAdd(Month, -6, mydate)) as varchar) + ' - ' + CAST(Year(DateAdd(Month, 6, mydate)) as varchar)

Here is some test Sql based on Simon's answer
DECLARE #basestartdate datetime, #baseenddate datetime
SET #basestartdate = CAST('1 April 1753' AS datetime)
SET #baseenddate = CAST('31 March 1754' AS datetime)
;
WITh TestData as
(
SELECT
CAST('1 April 2015' AS datetime) input,
CAST('1 April 2015' AS datetime) expectedstartdate,
CAST('31 March 2016' AS datetime) expectedenddate UNION SELECT
CAST('2 April 2015' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('31 December 2015' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('1 January 2016' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('28 February 2016' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('31 March 2016' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('1 April 2016' AS datetime),
CAST('1 April 2016' AS datetime),
CAST('31 March 2017' AS datetime)
),
Results AS
(
SELECT
input,
expectedstartdate,
DATEADD(MONTH,
12 * (DATEDIFF(MONTH, #basestartdate, input) / 12),
#basestartdate) startdate,
expectedenddate,
DATEADD(MONTH,
12 * (DATEDIFF(MONTH, #basestartdate, input) / 12),
#baseenddate) enddate
FROM testdata
)
SELECT
CASE
WHEN (expectedstartdate = startdate) THEN 'Pass' ELSE 'Fail'
END startdateresult,
CASE
WHEN (expectedenddate = enddate) THEN 'Pass' ELSE 'Fail'
END startdateresult
FROM results
ORDER BY input

Related

Number of days left in current month

Number of days left in a given month
How do I find the number of days left in the current month?
Example if current month is November and todays date is 16/11/2016
The Numbers of days in month – Elapse days = ? I want to do it dynamically
In my example 30 – 16 = 14
declare #date date
set #date='16 Nov 2016'
select datediff(day, #date, dateadd(month, 1, #date)) - 16 AS DaysLeft
Since this is sql server 2008 you can't use EOMonth (that was introduced in 2012 version).
You have to do some date adds and date diffs:
SELECT DATEDIFF(DAY,
GETDATE(),
DATEADD(MONTH,
1,
DATEADD(DAY, 1 - DAY(GETDATE()), GETDATE())
)
) - 1
explanations:
DATEADD(DAY, 1 - DAY(GETDATE()), GETDATE()) gets the first day of the current month, the wrapping DATEADD adds one month, and the wrapping DATEDIFF returns the number of days between the current date and the first date of the next month. This is why you need to subtruct 1 to get the correct number of days.
--For SQL 2012 And Above Version Use Below Query to Get Count Of Days Left In A Month
DECLARE #date DATE
SET #date=GETDATE()
SELECT DATEDIFF(DAY, #date,EOMONTH(#date))
-- And for Sql Server 2008 Use Below Query to Get Count of Days Left for the Month
DECLARE #date Date
SET #date=GETDATE()
SELECT DATEDIFF(DAY, #date, DATEADD(MONTH, 1, #date)) - DATENAME(DAY,GETDATE())
AS DaysLeft
Simply use the Datepart function:
declare #date date
set #date='16 Nov 2016'
select datediff(day, #date, dateadd(month, 1, #date)) - Datepart(DAY,#date)
Change your date to getdate()
declare #date date
set #date=GETDATE()
select datediff(day, #date, dateadd(month, 1, #date)) - DATENAME(DAY,GETDATE())
AS DaysLeft
DECLARE #date DATE SET #date='16 Nov 2016' SELECT DATEDIFF(DAY, #date,EOMONTH(#date))
Use EOMONTH and DATEDIFF functions
declare #date date
set #date='16 Nov 2016'
select datediff(day,#date,eomonth(#date)) as days_left
Use below solution For Below versions of sql server 2012
DECLARE #DATE DATE
SET #DATE='16 NOV 2016'
SELECT DATEDIFF(DAY,#DATE,DATEADD( MM,DATEDIFF(MM,0,#DATE)+1,0))-1 AS DAYS_LEFT
FUNCTION example
CREATE Or ALTER FUNCTION ReturnDaysLeftInMonth(#Date Date)
RETURNS Int
AS
BEGIN
RETURN DATEDIFF(DAY, #Date, EOMONTH(#Date)) + 1
END
Or use
Declare #Date Date
Set #Date=GETDATE()
DATEDIFF(DAY, #Date, EOMONTH(#Date)) + 1

Find missing period and determine whether consecutive before

I am currently working on a requirement to find the missing period and then determine whether it was consecutive before the missing period
Following is my sample table structure.
First step: In the following sample table look at last 6 months (2014 7 - 2014 12). Its missing two months 8 & 11. Take the first instance 8.
Second step: Go back 6 months from the first instance missing - (2014 2- 2014 7) - see whether they are missing any months. If No (everything is consecutive) - Select/Include this record if Yes (missing some months) - don't select this record.
Year Month
2014 1
2014 2
2014 3
2014 4
2014 5
2014 6
2014 7
2014 9
2014 10
2014 12
I can select last 6 records and partition by row number and see whether its missing any. But I am not sure how to find if its consecutive and also select the missing period.
I am trying to do as much filtration in Transact-SQL so that I can focus on other validations on c#.
Query I created to find first period missing(not complete)
SELECT f.TYEAR,f.TMONTH, f.TMONTH+1 AS MISSING FROM #TEMPTABLE AS F
LEFT OUTER JOIN #TEMPTABLE AS F2 ON f.TMONTH+1 = f2.TMONTH
WHERE f2.TAXPERIOD IS NULL
Note: The above example can span b/w two calendar years. 2013 mm - 2014 mm
This one has been tested, I've spent some time on it, please let me know if you're happy with the result and vote if yes, cheers :-) PS: The table dbo.Months_and_Years contains your data (with the 2 missing months)
CREATE TABLE dbo.Test_Table (
[Year] SMALLINT,
[Month] TINYINT
);
INSERT INTO dbo.Test_Table
VALUES
(2014, 1),
(2014, 2),
(2014, 3),
(2014, 4),
(2014, 5),
(2014, 6),
(2014, 7),
(2014, 9),
(2014, 10),
(2014, 12);
DECLARE #MinValue TINYINT = 1
DECLARE #MaxValue TINYINT = 100
WHILE #MinValue < = #MaxValue
BEGIN
DECLARE #Missing_Month TINYINT = (
SELECT TOP 1 A.RowID
FROM (
SELECT DENSE_RANK() OVER ( ORDER BY [month]) AS RowID ,
*
FROM dbo.Test_Table
) AS A
WHERE A.RowID <> A.[Month]
)
SELECT #Missing_Month
IF #Missing_Month IS NULL
BREAK
ELSE
INSERT INTO dbo.Test_Table
VALUES (2014, #Missing_Month)
SET #MinValue = #MinValue + 1
END
-- Check your results ---
SELECT A.*
FROM dbo.Test_Table AS A
LEFT JOIN dbo.Months_and_Years AS B ON A.[Month] = B.[Month]
WHERE B.[Month] IS NULL;
I think below code should work, though I've not tested it properly. But you will get the idea -
DECLARE #TmpBaseTable TABLE ([Year] SMALLINT, [Month] TINYINT)
DECLARE #TmpSixMonthTable TABLE (TmpYear SMALLINT, TmpMonth TINYINT)
DECLARE #TmpDate DATE
DECLARE #MissingYear SMALLINT
DECLARE #MissingMonth TINYINT
DECLARE #TmpCount TINYINT
INSERT INTO #TmpBaseTable ([Year], [Month])
SELECT 2014, 1 UNION ALL
SELECT 2014, 2 UNION ALL
SELECT 2014, 3 UNION ALL
SELECT 2014, 4 UNION ALL
SELECT 2014, 5 UNION ALL
SELECT 2014, 6 UNION ALL
SELECT 2014, 7 UNION ALL
SELECT 2014, 8 UNION ALL
SELECT 2014, 9 UNION ALL
SELECT 2014, 10 UNION ALL
SELECT 2014, 11 UNION ALL
SELECT 2014, 12 UNION ALL
SELECT 2015, 1 UNION ALL
SELECT 2015, 3 UNION ALL
SELECT 2015, 4
SELECT TOP 1 #TmpDate = CAST(CAST(tmpYear AS VARCHAR) + '-' + CAST(tmpMonth AS VARCHAR) + '-' + CAST(1 AS VARCHAR) AS DATE)
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY [Year], [Month]) AS RowID, [Month] AS tmpMonth, [Year] AS tmpYear
FROM #TmpBaseTable
)
tmp ORDER BY RowID DESC
INSERT INTO #TmpSixMonthTable (TmpMonth, TmpYear)
SELECT DATEPART(MONTH, DATEADD (MONTH, -5, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -5, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -4, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -4, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -3, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -3, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -2, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -2, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -1, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -1, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -0, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -0, #TmpDate))
SELECT TOP 1 #MissingMonth = tmpSix.TmpMonth, #MissingYear = tmpSix.TmpYear FROM #TmpSixMonthTable tmpSix
LEFT OUTER JOIN #TmpBaseTable tmpBase ON tmpSix.TmpMonth = tmpBase.[Month] AND tmpSix.TmpYear = tmpBase.[Year]
WHERE tmpBase.[Year] IS NULL
SET #TmpDate = CAST(CAST(#MissingYear AS VARCHAR) + '-' + CAST(#MissingMonth AS VARCHAR) + '-' + CAST(1 AS VARCHAR) AS DATE)
DELETE FROM #TmpSixMonthTable
INSERT INTO #TmpSixMonthTable (TmpMonth, TmpYear)
SELECT DATEPART(MONTH, DATEADD (MONTH, -6, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -6, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -5, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -5, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -4, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -4, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -3, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -3, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -2, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -2, #TmpDate)) UNION ALL
SELECT DATEPART(MONTH, DATEADD (MONTH, -1, #TmpDate)), DATEPART(YEAR, DATEADD (MONTH, -1, #TmpDate))
SELECT #TmpCount = COUNT(1) FROM #TmpSixMonthTable tmp1
INNER JOIN #TmpBaseTable tmp2 ON tmp1.TmpMonth = tmp2.[Month] AND tmp1.TmpYear = tmp2.[Year]
IF(#TmpCount = 6)
BEGIN
SELECT tmp2.[Month], tmp2.[Year] FROM #TmpSixMonthTable tmp1
INNER JOIN #TmpBaseTable tmp2 ON tmp1.TmpMonth = tmp2.[Month] AND tmp1.TmpYear = tmp2.[Year]
END
There can be a smarter way than this :)

How can I use GETDATE() to get month and year from the past month?

How can I get it to one statement that can get me
last month and this year?
I have a INSERT INTO and in a column report_date [datetime]
insert into table_a (report_date) values ( ??);
i want to show this past month and year,
So for example today is 4/21/2014
so it would show 3/2014 in the column
If today was MAY 1 2014 , it would show 4/2014?
Is this possible or does it have to have a day?
You're looking for the DATEADD function:
SELECT DATEPART(month, DATEADD(month, -1, GETDATE()), DATEPART(year, DATEADD(month, -1, GETDATE())
If you are trying to get 'last month' with 'this year' you could do:
SELECT CAST(
CAST(YEAR(GETDATE()) AS VARCHAR) + '-' +
CAST(MONTH(GETDATE())-1 AS VARCHAR) + '-' +
CAST(DAY(GETDATE()) AS VARCHAR)
AS DATETIME)
But then in JAN 2015, it would return DEC 2015.
If you just want last month, use the 'DATEADD' function.
SELECT DATEADD(MONTH, -1, GETDATE())

SQL Get data in this year

i have a DB with a atribute "Date" which is a string ...
its format is:
"Jan 5 2014 6:26 PM"
and would like to get the number of rows where the date is this year.
already know how to convert the date:
SELECT convert(datetime, 'Oct 23 2012 11:01AM')
i found this code but I do not know how to join the two
select * from datetimes2
where dtm2 >= CAST(CURRENT_TIMESTAMP AS DATE)
and dtm2 < DATEADD(DD, 1, CAST(CURRENT_TIMESTAMP AS DATE))
;
Now I do not know how to do what I want :(
Is this what you looking for ?
DECLARE #datetime DATETIME = 'Jan 5 2014 6:26 PM'
SELECT
*
FROM datetimes2
WHERE [Date] >= CONVERT(DATETIME, CAST(DATEPART(YEAR, #datetime) AS VARCHAR) + '-01-01')
AND [Date] <= CONVERT(DATETIME, CAST(DATEPART(YEAR, #datetime) AS VARCHAR) + '-12-31')
This will get the records for complete year 2014. Hope this helps!
As simple as (assuming SQL server, given convert() )
select * from mytable where year( convert(datetime, date) ) = year( getDate() )
?

calculate fiscal year in sql select statement?

I have a date field that needs to return in fiscal year format. example
Start_Date Year
04/01/2012 - 2013
01/01/2012 - 2012
09/15/2013 - 2014
We need to calculate
04/01/2012 to 03/31/2013 is FY 2013
and
04/01/2013 to 03/31/2014 is FY 2014
How can we do that in select statement?
David has a very good solution. A simpler expression is:
select year(dateadd(month, -3, start_date)) as FiscalYear
That is, subtract 3 months and take the year.
EDIT:
As noted in the comment, this seems to produce one year too early. Here are two solutions:
select year(dateadd(month, 9, start_date)) as FiscalYear
select 1 + year(dateadd(month, -3, start_date)) as FiscalYear
SELECT CASE WHEN DatePart(Month, Start_Date) >= 4
THEN DatePart(Year, Start_Date) + 1
ELSE DatePart(Year, Start_Date)
END AS Fiscal_Year
FROM data
I just chose to do it this way. It's easy and you can replace the 09,30 with whatever you want your fiscal year end to be. Not sure if this works in anything but SQL Server though.
CASE
WHEN CAST(GETDATE() AS DATE) >
SMALLDATETIMEFROMPARTS(DATEPART(YEAR,GETDATE()),09,30,00,000)
THEN
DATEPART(YEAR,GETDATE()) + 1 ELSE DATEPART(YEAR,GETDATE())
END AS FY
For Australian financial year, use the following:
SELECT
year(dateadd(MONTH, 6, DateColumn)) AS FY,
...
FROM ...
Assuming that you have a table Fiscal_Year with Start_Date per Year, and you want to find the fiscal year for a given date #Date:
SELECT MIN(Year) WHERE #Date >= Start_Date FROM Fiscal_Year
Declare #t table(StartDate date ,Year1 int)
insert into #t values('04/01/2012',2013),('01/01/2012',2012),('09/15/2013',2014)
;with CTE as
(select max(year1) maxyear from #t)
, cte1 as
(select cast('04/01/'+convert(varchar(4),a.year1) as date) FromFY,dateadd(day,-1,dateadd(year,1,cast('04/01/'+convert(varchar(4),a.year1) as date))) ToFY
,b.year1 from #t a inner join (select min(year1)year1 from #t) b on a.year1=b.year1
union all
select cast(dateadd(day,1,ToFY) as date),cast(dateadd(year,1,ToFY) as date),year1+1 year1 from cte1 where year1<=(select maxyear from cte)
)
select * from cte1
DECLARE #STARTDATE DATETIME, #ENDDATE DATETIME,#CURR_DATE DATETIME
SET #CURR_DATE='2015-01-30'
IF MONTH(#CURR_DATE) IN (1,2,3)
BEGIN
SET #STARTDATE= CAST( CAST(YEAR(#CURR_DATE)-1 AS VARCHAR)+'/04/01' AS DATE)
SET #ENDDATE= CAST( CAST(YEAR(#CURR_DATE) AS VARCHAR)+'/03/31' AS DATE)
END
ELSE
BEGIN
SET #STARTDATE= CAST( CAST(YEAR(#CURR_DATE) AS VARCHAR)+'/04/01' AS DATE)
SET #ENDDATE= CAST( CAST(YEAR(#CURR_DATE)+1 AS VARCHAR)+'/03/31' AS DATE)
END
SELECT #STARTDATE AS ST_FI,#ENDDATE AS END_FY
...something simple :)
(YEAR(DATEADD(Month,-((DATEPART(Month,[Date])+5) %12),[Date]))+) AS Financial_Year
declare #Date smalldatetime, #FiscalYearStartMonth tinyint
set #Date = GETDATE();
set #FiscalYearStartMonth = 1; -- Jan
print convert(varchar(4),
case when MONTH(#Date) < #FiscalYearStartMonth
then YEAR(#Date) -1
else YEAR(#Date) end)
assuming #Date is your [Start_Date] field, you can:
select * from yourTable
group by convert(varchar(4),
case when MONTH([Start_Date]) < #FiscalYearStartMonth
then YEAR([Start_Date]) -1
else YEAR([Start_Date]) end)
Hope this helps
This is what would look like in oracle to get current financial year. Enter the date for which you want to find fiscal year in place of sysdate
SELECT '01-APR-'
||TO_CHAR((add_months(**sysdate**,-3)),'YYYY') FIN_YEAR_START_DATE,
'31-MAR-'
||(TO_CHAR((add_months(**sysdate**,-3)),'YYYY')+1) FIN_YEAR_END_DATE
FROM dual;
For only year format (FY 2020) use following query:
SELECT tender_opening_date,CASE WHEN MONTH( order_date) >= 4
THEN CONCAT('FY ',YEAR(( order_date)) +1 )
ELSE CONCAT('FY ',YEAR( order_date)-1 )
END AS Fiscal_Year
FROM orders_tbl
For full financial Year (FY 2019-20) use following query:
SELECT tender_opening_date,CASE WHEN MONTH( order_date) >= 4
THEN CONCAT('FY ',YEAR( order_date),'-',DATE_FORMAT( order_date,'%y') +1 )
ELSE CONCAT('FY ',YEAR( order_date)-1,'-',DATE_FORMAT( order_date,'%y') )
END AS Fiscal_Year
FROM orders_tbl