-2

我想要一个计算财政年度的函数。财政年度必须从三月的第一个星期一开始。谢谢!例子:

CREATE FUNCTION dbo.fnc_FiscalYear( @AsOf DATETIME ) 
RETURNS INT 
AS BEGIN 
DECLARE @Answer INT 
SET DATEFIRST 1 
IF ( MONTH(@AsOf) < 3 ) 
or MONTH(@AsOf=3) and datename(weekday, @AsOf) = 'Monday' and datepart(day, @AsOf)>=1 and datepart(day, @AsOf)<=7;
SET @Answer = YEAR(@AsOf) - 1 
ELSE SET @Answer = YEAR(@AsOf) 
RETURN @Answer 
END 
GO

但它不工作

4

3 回答 3

0

这样做的逻辑很棘手——尤其是在 3 月的第一周:

CREATE FUNCTION dbo.fnc_FiscalYear (
    @AsOf DATETIME
) 
RETURNS INT AS
BEGIN 
  RETURN( CASE WHEN MONTH(@AsOf) < 3 THEN YEAR(@AsOf) - 1
               WHEN MONTH(@AsOf) > 3 THEN YEAR(@AsOf)
               WHEN DAY(@AsOf) >= 7 THEN YEAR(@AsOf)
               WHEN DATENAME(@AsOf) = 'Monday' OR
                    DATENAME(@AsOf) = 'Tuesday' AND DAY(@AsOf) >= 2 OR
                    DATENAME(@AsOf) = 'Wednesday' AND DAY(@AsOf) >= 3 OR
                    DATENAME(@AsOf) = 'Thursday' AND DAY(@AsOf) >= 4 OR
                    DATENAME(@AsOf) = 'Friday' AND DAY(@AsOf) >= 5 OR
                    DATENAME(@AsOf) = 'Saturday' AND DAY(@AsOf) >= 26
               THEN YEAR(@AsOf)
               ELSE YEAR(@AsOf) - 1
          END);
END ;
GO
于 2019-11-16T20:36:09.593 回答
0

( @@DateFirst + DatePart( weekday, SampleDate ) - 1 ) % 7 + 1将始终返回一个整数 from 0to6对应0于周日,无论是否设置DateFirst字符串Language操作。

将表达式调整为( @@DateFirst + DatePart( weekday, SampleDate ) - 2 ) % 7将周期的开始时间从星期日转移到星期一以及范围06进而简化以下代码:

create function dbo.FiscalYear( @Date as Date )
  returns Int
  begin
  return Year( @Date ) - case
    when Month( @Date ) <= 2 then 1 -- January and February are always part of the prior year.
    -- In March it is the prior year only in the first week and if the calculated
    --   DoW is less than the day of the month.
    when Month( @Date ) = 3 and Day( @Date ) < 7 and
      ( @@DateFirst + DatePart( weekday, @Date ) - 2 ) % 7 >= Day( @Date ) then 1
    else 0 end;
  end;

用样本数据测试函数:

with
  -- Generate sample dates for 20 years.
  YearOffsets as (
    select 0 as YearOffset
    union all
    select YearOffset + 1
      from YearOffsets
      where YearOffset < 20 ),
  SampleDates as (
    select Cast( DateAdd( year, YearOffset, '2000-02-28' ) as Date ) as SampleDate, 1 as Counter
      from YearOffsets
    union all
    select DateAdd( day, 1, SampleDate ), Counter + 1
      from SampleDates
      where Counter < 10 )
  -- Calculate the Fiscal Year for each sample date.
  select SampleDate, DateName( weekday, SampleDate ) as WeekDay,
    ( @@DateFirst + DatePart( weekday, SampleDate ) - 2 ) % 7 as DayOfWeek, -- 0 = Monday.
    dbo.FiscalYear( SampleDate ) as FiscalYear
    from SampleDates
    order by SampleDate;
于 2019-11-17T16:12:30.053 回答
0

您的脚本似乎存在许多语法错误。试试这个。我已经删除了 SET 并在 if 语句处返回。另外,请注意 if 语句的分组。

CREATE FUNCTION dbo.fnc_FiscalYear( @AsOf DATETIME ) 
RETURNS INT 
AS BEGIN 
  DECLARE @Answer INT 
  IF (( MONTH(@AsOf) < 3 ) 
  OR (MONTH(@AsOf) = 3 
      AND DATENAME(weekday, @AsOf) = 'Monday' 
      AND datepart(day, @AsOf) >= 1 
      AND datepart(day, @AsOf)<=7))
    RETURN (YEAR(@AsOf) - 1)
  RETURN YEAR(@AsOf) 
END 
GO
于 2019-11-16T20:07:23.120 回答