【问题标题】:calculate financial periods into temp table将财务期间计算到临时表中
【发布时间】:2018-11-03 13:32:39
【问题描述】:

我有一个客户报告财政年度中的 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)

谁能帮忙解决我哪里出错了?

戴夫

附加: sql 的示例结果集将如下所示:

【问题讨论】:

  • 我猜没有人能帮上忙。您需要提供样本数据、期望的结果以及您正在做什么的解释。第一个循环之后的“崩溃”并不是一个非常准确的描述。
  • 我应该补充一点,这个脚本是给我一个只有开始日期结束日期和期间编号的临时表。
  • 这种问题真的让我本能地说——日期统计表。
  • 没有人报告每年 13 个 27 天的周期。因为那是 351 天,一年有 365 天或 366 天。他们可能有自己使用的算法,如果有的话向他们索取。或者,为了简化生活,在您的数据库中创建一个日历表。然后在每个日期手动或半手动更新一些元数据(会计年度id、财政季度id、财政月份id等)。使用从 (例如) 2000-01-01 到 2099-12-31 的日期填充它,只要它涵盖您的应用程序将需要的每个日期。然后你可以从那个表中索引地狱。它将节省很多的复杂性。
  • 嗨,戈迪,感谢您与我们联系。我就我需要的帮助而言,你在这里看到的就是你得到的。我只是尝试使用 while 循环将一些计算日期插入临时表。抱歉,如果帖子标题有点偏离,我的问题在我打字时有点变形。

标签: sql date while-loop temp-tables


【解决方案1】:

尽管同意你们需要为我提供工作的日期,但我不能让任务打败我,所以我终于写了一个可行的答案。

它结合了我在此处找到的用于连接日期的标量函数(感谢 Brian 提供的函数):

Create a date with T-SQL

使用上面的 Gordons 代码

获得最终产品:

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

感谢大家的贡献。

问候,

戴夫

【讨论】:

    【解决方案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;
    

    【讨论】:

    • Gordon 谢谢你,我应该提一下,我在 2008R2 上,所以我担心lead() 不是一个选项。
    猜你喜欢
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多