将财务周期计算为临时 table
calculate financial periods into temp table
我有一个客户在财政年度的 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 的示例结果集将如下所示:
如果您尝试在两个日期之间生成时间段,您可以使用递归 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;
尽管同意你们需要为我提供工作日期,但我不能让任务打败我,所以我终于写出了一个有效的答案。
它结合了我在这里找到的用于连接日期的标量函数(感谢 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
感谢大家的贡献。
此致,
戴夫
我有一个客户在财政年度的 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 的示例结果集将如下所示:
如果您尝试在两个日期之间生成时间段,您可以使用递归 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;
尽管同意你们需要为我提供工作日期,但我不能让任务打败我,所以我终于写出了一个有效的答案。
它结合了我在这里找到的用于连接日期的标量函数(感谢 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
感谢大家的贡献。
此致,
戴夫