返回日期范围之间的财务年度列表

时间:2014-08-28 13:46:13

标签: sql-server

也许我过度思考这个问题,但我有点难过。

我试图按月,按财政年度汇总数据,每个财政年度返回一行,每个月有一列。

我可以轻松地每月返回一列,但是试图以行为单位来回归财务年度是非常困难的。

我的理论是,一旦我将财政年度选为一行,我可以简单地将其加入按财务年/月总结的子查询中,每1个给我1个。

麻烦是财政年度从8月1日开始。查询的日期范围可能从1个财政年度到可能跨越5年的日期范围不等。

例如,如果我的日期范围是01/08 / 2013-31 / 07/2014,我希望财政年度返回:

2013/2014

如果我的日期范围是01/08 / 2012-31 / 07/2014,我希望将以下内容作为财务年度返回:

2012/2013 
2013/2014

如果我的日期范围是01/01 / 2012-28 / 08/2014,我希望将以下内容作为财务年度返回:

2011/2012
2012/2013
2013/2014
2014/2015

到目前为止,这是我的工作,但它并没有按预期工作。

  DECLARE @DateFrom datetime, @DateTo datetime
SET @DateFrom = '2011-08-01'
set @DateTo = '2014-07-31'


; with  FinYr as
        (
        select  @DateFrom as AllDate, @DAteTo as EndDate, case when datepart(MONTH, @DateFrom) < 8 then convert(varchar(4),datepart(year, @DateFrom)-1)+'/'+convert(varchar(4),datepart(year, @DateFrom)) else convert(varchar(4),datepart(year, @DateFrom))+'/'+convert(varchar(4),datepart(year, @DateFrom)+1) End as FinYear
        union all
        select  dateadd(year,1,AllDate) as AllDate, dateadd(year,1,EndDate) as EndDate,case when datepart(MONTH, dateadd(year,1,AllDate)) < 8 then convert(varchar(4),datepart(year, dateadd(year,1,AllDate))-1)+'/'+convert(varchar(4),datepart(year, dateadd(year,1,AllDate))) else convert(varchar(4),datepart(year, dateadd(year,1,AllDate)))+'/'+convert(varchar(4),datepart(year, dateadd(year,1,AllDate))+1) End as FinYear
        from    FinYr
        where   dateadd(year,-1,EndDate) <= convert(datetime,(convert(varchar(4),year(@Dateto))+'-07-31'))
        )
select  AllDate,EndDate, FinYear
from    FinYr

2 个答案:

答案 0 :(得分:1)

您可以使用计数器或数字表来执行此类操作。在我的代码中,我已经创建了计数表。这是一种零读取类型的实现......超快。

DECLARE @DateFrom datetime, @DateTo datetime;
SET @DateFrom = '2011-08-01';
set @DateTo = '2014-07-31';

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )

select CAST(N as CHAR(4)) + '/' +  CAST(N + 1 as CHAR(4))
from cteTally
where N >= DATEPART(YEAR, @DateFrom)
and N <= DATEPART(YEAR, @DateTo);

确定更新后的要求,只需轻微调整上述代码即可完成此操作。这应该可以帮助你。

select CAST(N as CHAR(4)) + '/' +  CAST(N + 1 as CHAR(4))
from cteTally
where N >= case when DATEPART(MONTH, @DateFrom) > 6 then DATEPART(YEAR, @DateFrom) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateFrom)) end
and N <= case when DATEPART(MONTH, @DateTo) < 6 then DATEPART(YEAR, @DateTo) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateTo)) end

我想我看到我在那里做错了什么....试试这个。

select CAST(N as CHAR(4)) + '/' +  CAST(N + 1 as CHAR(4))
, case when DATEPART(MONTH, @DateTo) < 8 then DATEPART(YEAR, DATEADD(YEAR, -1, @DateTo)) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateTo)) end
from cteTally
where N >= case when DATEPART(MONTH, @DateFrom) > 6 then DATEPART(YEAR, @DateFrom) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateFrom)) end
and N <= case when DATEPART(MONTH, @DateTo) < 8 then DATEPART(YEAR, DATEADD(YEAR, -1, @DateTo)) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateTo)) end

答案 1 :(得分:1)

我相信这会显示您想要的年份列表:

DECLARE 
    @DateFrom datetime, 
    @DateTo   datetime
SET @DateFrom = '2011-01-01'
SET @DateTo = '2014-07-31'


SELECT CAST(YearList AS VARCHAR(4)) + '/' + CAST((YearList +1) AS VARCHAR(4)) AS FiscalYear
FROM
  (
    SELECT 
        DATEPART(YEAR, @DateFrom) - CASE WHEN DATEPART(MONTH, @DateFrom) >= 8 THEN 0 ELSE 1 END + 
        ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY (SELECT NULL)) -1 AS YearList
    FROM sys.all_objects
  ) q
WHERE YearList <= DATEPART(YEAR, @DateTo) - CASE WHEN DATEPART(MONTH, @DateTo) >= 8 THEN 0 ELSE 1 END