• If you want some flexibility to change fiscal year date ranges the case statements are a bit tedious. I happened to need some fiscal year calculations just the other day so came up with this table-valued function:

    CREATE FUNCTION [dbo].[tvfGetFiscalYear]

    (

    @YearStart VARCHAR(10)

    ,@YearEnd VARCHAR(10)

    ,@InputMonth INT

    ,@InputYear INT

    )

    RETURNS @FYear TABLE

    (

    FMonth INT

    ,FYear INT

    ,IMonth INT

    ,IYear INT

    )

    AS

    BEGIN

    DECLARE

    @FiscalYear INT

    ,@FiscalMonth INT

    ,@FiscalYearStart DATE

    ,@FiscalYearEnd DATE

    ,@FStartMonth DATE

    ,@InputDate DATE

    SET @InputDate = CAST(CAST(@InputMonth AS VARCHAR(2))+'/01/'+CAST(@InputYear AS VARCHAR(4)) AS DATE)

    SET @FiscalYearEnd = CAST(CAST(DATEPART(yyyy,@InputDate) AS CHAR(4))+'/'+@YearEnd AS DATE)

    SET @FiscalYearStart = CAST(CAST(DATEPART(yyyy,DATEADD(yy,-1,@InputDate)) AS CHAR(4))+'/'+@YearStart AS DATE)

    IF DATEDIFF(day,@FiscalYearEnd,@InputDate) > 0

    SET @FiscalYear = YEAR(DATEADD(yy,1,@InputDate))

    ELSE IF DATEDIFF(day,@InputDate,@FiscalYearStart) > 0

    SET @FiscalYear = YEAR(DATEADD(yy,-1,@InputDate))

    ELSE

    SET @FiscalYear = YEAR(@InputDate)

    SET @FStartMonth = CAST(@YearStart+'/'+CAST(@FiscalYear-1 AS CHAR(4)) AS DATE)

    SET @FiscalMonth = CAST(DATEDIFF(MONTH,@FStartMonth,@InputDate) AS INT)+1

    INSERT INTO @FYear

    SELECT

    @FiscalMonth

    ,@FiscalYear

    ,@InputMonth

    ,@InputYear

    RETURN

    END

    Then, use the function like this and get the same results:

    DECLARE

    @YearStart VARCHAR(10)

    ,@YearEnd VARCHAR(10)

    SET @YearStart = '10/1'

    SET @YearEnd = '9/30'

    SELECT

    COUNT(ur.UserId) AS [User Count]

    ,DATENAME(MONTH,ur.Registrationdate) AS mnth

    ,YEAR(ur.Registrationdate) AS Yr

    ,'FY '+CAST((SELECT FYear FROM dbo.tvfGetFiscalYear(@YearStart,@YearEnd,MONTH(ur.Registrationdate),YEAR(ur.Registrationdate))) AS VARCHAR(7)) AS FY

    ,(SELECT FMonth FROM dbo.tvfGetFiscalYear(@YearStart,@YearEnd,MONTH(ur.Registrationdate),YEAR(ur.Registrationdate))) AS FYMonth

    FROM

    dbo.UserRegistration AS ur

    WHERE

    ur.UserId > 0

    GROUP BY

    DATENAME(MONTH,ur.Registrationdate)

    ,YEAR(ur.Registrationdate)

    ,MONTH(ur.Registrationdate)

    ORDER BY

    FYMonth

    ,yr

    Probably an even better method would be to use the function's date logic in a stored procedure to calculate the fiscal year/month for all of the rows and then join the results to the UserRegistration table instead of using a function in the select statement. For a large dataset that would likely be more efficient. But I'll leave that for someone else. 😉