将财务期计算为临时表

时间:2018-05-24 10:46:01

标签: sql date while-loop temp-tables

我有一位客户在财政年度报告了13个27天的期间,我正在尝试制定一些动态SQL来确定发票的报告期间。

这是我到目前为止所做的,但是while循环在第一次循环后崩溃。

IF OBJECT_ID('#Periods', 'U') IS NOT NULL
drop table #Periods

create table #Periods
([start_date] date, [end_date] date, Period varchar(3) )

declare @LYdt datetime,
        @CYdt datetime,
        @Period int

SET @Period = 0
SET @LYdt = '09/01/2016'
SET @CYdt = '09/01/2017'
While @Period  <=13

insert #Periods
select 
[Start_Date] = dateadd(mm,datediff(mm,'',@LYdt),'') - datepart(dw,dateadd(mm,datediff(mm,'',@LYdt),'')+0)+ 22,
[End Date] = (dateadd(mm,datediff(mm,'',@LYdt),'') - datepart(dw,dateadd(mm,datediff(mm,'',@LYdt),'')+0)+ 22)+27,
[Period] = 'P'+ convert(varchar(2),@Period)



SET @Period = @Period + 1
SET @LYdt =  dateadd(d,27,@LYdt)
SET @CYdt = dateadd(d,27,@CYdt)

有人可以协助我出错吗?

戴夫

addiditonal:  sql的示例结果集如下所示:

sample data set

2 个答案:

答案 0 :(得分:2)

如果您尝试在两个日期之间生成句点,则可以使用递归CTE:

with periods as (
      select cast('2016-09-01' as date) as start_date, 1 as lev
      union all
      select dateadd(day, 27, start_date), lev + 1
      from periods
      where start_date < '2017-09-01'
     )
select start_date,
       lead(start_date) over (order by start_date) as end_date,
       'P' + right('00' + cast(lev as varchar(255)), 2) as period_num
from periods;

编辑:

您可以通过以下方式轻松完成此操作:

with periods as (
      select cast('2016-09-01' as date) as start_date, 1 as lev
      union all
      select dateadd(day, 27, start_date), lev + 1
      from periods
      where start_date < '2017-09-01'
     )
select start_date,
       dateadd(day, 27, start_date) as end_date,
       'P' + right('00' + cast(lev as varchar(255)), 2) as period_num
from periods;

答案 1 :(得分:0)

尽管与你们一致同意他们需要提供我合作的日期,但我无法让任务击败我,所以我终于写了一个有效的答案。

它结合了一个标量函数,用于连接我在这里找到的日期(感谢Brian的功能):

Create a date with T-SQL

使用上面的Gordons Code

获得最终产品:

declare @LY datetime,
        @TY datetime,
        @FD datetime,
        @TY_DATE datetime,
        @LY_DATE datetime,
        @FD_DATE datetime,
        @Use_date datetime

select @LY = dbo.datemaker(datepart(year,getdate())-2, 9, 1)
select @TY = dbo.datemaker(datepart(year,getdate())-1, 9, 1)
Select @FD = dbo.datemaker(datepart(year,getdate()), 9, 1)
 select @LY_DATE =  dateadd(mm,datediff(mm,'',@LY),'') - datepart(dw,dateadd(mm,datediff(mm,'',@LY),'')+0)+ 22
 select @TY_DATE = dateadd(mm,datediff(mm,'',@TY),'') - datepart(dw,dateadd(mm,datediff(mm,'',@TY),'')+0)+ 22
 select @FD_DATE = dateadd(mm,datediff(mm,'',@FD),'') - datepart(dw,dateadd(mm,datediff(mm,'',@FD),'')+0)+ 22

select @use_date = case when(convert(date,getdate()) >= @FD_DATE) then @TY_DATE ELSE @LY_DATE END;



with periods as (
      select @use_date as start_date, 1 as lev
      union all
      select dateadd(day, 28, start_date), lev + 1
      from periods
      where start_date < dateadd(year,1,start_date) and
      lev <=12)



select start_date as [Start_Date],
       dateadd(day, 27, start_date) as end_date,
       'P' + right('00' + cast(lev as varchar(255)), 2) +'LY' as period_num

from periods

union all

select dateadd(year,1,start_date) as [Start_Date],
       dateadd(year,1,dateadd(day, 27, start_date)) as end_date,
       'P' + right('00' + cast(lev as varchar(255)), 2) +'TY' as period_num



from periods;

CREATE FUNCTION [dbo].[Datemaker]
(
    @Year INT,
    @Month INT,
    @DayOfMonth INT

)
RETURNS DATETIME
AS
BEGIN

    RETURN 
            DATEADD(day, @DayOfMonth - 1, 
            DATEADD(month, @Month - 1, 
            DATEADD(Year, @Year-1900, 0)))

END

GO

感谢你们所有人的贡献。

此致

戴夫