如何创建SQL自定义4-4-5财务期间日期表
我正在尝试创建一个SQL脚本来生成定制的财务日期表,以便在2010-2030年间进行报告。日历松散地基于4-4-5日历,除非有特定的周期规则 规则如下:如何创建SQL自定义4-4-5财务期间日期表,sql,sql-server,database,tsql,datetime,Sql,Sql Server,Database,Tsql,Datetime,我正在尝试创建一个SQL脚本来生成定制的财务日期表,以便在2010-2030年间进行报告。日历松散地基于4-4-5日历,除非有特定的周期规则 规则如下: 财政年度总是从1月1日开始 财政年度总是在12月31日结束 每个会计期间(月末)的最后一天总是在周六 会计季度与自定义期间对齐 见下面的例子 2016年财务日历(闰年) 2017年财务日历 如果您能给我一些指导,让我用通常的日期维度和期间和季度的自定义财务值创建此表,我将不胜感激 我忽略了您的销售快报和最终结果标志,因为您的问题中未包含
- 财政年度总是从1月1日开始
- 财政年度总是在12月31日结束
- 每个会计期间(月末)的最后一天总是在周六
- 会计季度与自定义期间对齐
如果您能给我一些指导,让我用通常的日期维度和期间和季度的自定义财务值创建此表,我将不胜感激 我忽略了您的
销售快报
和最终结果
标志,因为您的问题中未包含的内容似乎有一定程度的自定义逻辑。如果您还想包括美国假期,您还需要维护一个单独的日期表,您可以加入到该表中,以将其纳入下表中所做的任何日期计算中
除此之外,您最大的问题似乎是计算月底天数,因为这些天数经常变动。这可以通过使用窗口函数和提取理货表中生成的Date
值的一部分来实现。我已经包括了一系列不同的date
函数,如果您正在使用这个参考表,您可以使用这些函数作为示例,建议不要动态创建。但是,如果要创建静态表,最好只创建一次,然后手动整理特殊日期列表,以确保它们是正确的:
declare @StartDate date = '20100101';
declare @EndDate date = '20301231';
declare @MonthEndDay int = 7; -- Saturday
-- Tally table creates all the date values which can then be used as your date dimension.
with t(t) as(select t from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(t))
,d(d) as(select top(select datediff(d,@StartDate,@EndDate)+1) dateadd(d,row_number()over(order by (select null))-1,@StartDate)from t t1,t t2,t t3,t t4,t t5,t t6)
,c as(select d as FullDate
,case when month(d) = 12 -- This logic is to handle the final day of the year.
then case when day(d) = 31 then 1 else 0 end
else case when sum(case when datepart(weekday,dateadd(d,-1,d)) = @MonthEndDay then 1 else 0 end) over (partition by year(d) order by d) in(4,8,13,17,21,26,30,34,39,43,47,52)
and datepart(weekday,d) = @MonthEndDay
then 1
else 0
end
end as FiscalPeriodEndDate
,sum(case when datepart(weekday,dateadd(d,-1,d)) = @MonthEndDay then 1 else 0 end) over (partition by year(d) order by d) as WeekNum
,((sum(case when datepart(weekday,dateadd(d,-1,d)) = @MonthEndDay then 1 else 0 end) over (partition by year(d) order by d)-1) / 13)+1 as QuarterNum
from d
)
select FullDate
,FiscalPeriodEndDate
,WeekNum
-- Where there is a 53rd week it will show as the 5th Quarter per the calculation above, so change it to 4th.
,case when QuarterNum > 4 then 4 else QuarterNum end as QuarterNum
-- Examples of different date functions you can use to make querying and reporting easier and when indexed properly, a lot faster.
,year(FullDate) as DateYear
,month(FullDate) as DateMonth
,day(FullDate) as DateDay
,datepart(weekday,FullDate) as DateWeekDayNum
,datename(weekday,FullDate) as DateWeekDayName
from c
order by FullDate;
输出-请注意您的财务期间的FiscalPeriodEndDate
标志:
+------------+---------------------+---------+------------+----------+-----------+---------+----------------+-----------------+
| FullDate | FiscalPeriodEndDate | WeekNum | QuarterNum | DateYear | DateMonth | DateDay | DateWeekDayNum | DateWeekDayName |
+------------+---------------------+---------+------------+----------+-----------+---------+----------------+-----------------+
| ...etc | | | | | | | | |
| 2016-01-28 | 0 | 4 | 1 | 2016 | 1 | 28 | 5 | Thursday |
| 2016-01-29 | 0 | 4 | 1 | 2016 | 1 | 29 | 6 | Friday |
| 2016-01-30 | 1 | 4 | 1 | 2016 | 1 | 30 | 7 | Saturday |
| 2016-01-31 | 0 | 5 | 1 | 2016 | 1 | 31 | 1 | Sunday |
| 2016-02-01 | 0 | 5 | 1 | 2016 | 2 | 1 | 2 | Monday |
| ...etc | | | | | | | | |
| 2016-02-25 | 0 | 8 | 1 | 2016 | 2 | 25 | 5 | Thursday |
| 2016-02-26 | 0 | 8 | 1 | 2016 | 2 | 26 | 6 | Friday |
| 2016-02-27 | 1 | 8 | 1 | 2016 | 2 | 27 | 7 | Saturday |
| 2016-02-28 | 0 | 9 | 1 | 2016 | 2 | 28 | 1 | Sunday |
| 2016-02-29 | 0 | 9 | 1 | 2016 | 2 | 29 | 2 | Monday |
| ...etc | | | | | | | | |
+------------+---------------------+---------+------------+----------+-----------+---------+----------------+-----------------+
我忽略了您的销售快报
和最终结果
标志,因为您的问题中未包含的内容似乎有一定程度的自定义逻辑。如果您还想包括美国假期,您还需要维护一个单独的日期表,您可以加入到该表中,以将其纳入下表中所做的任何日期计算中
除此之外,您最大的问题似乎是计算月底天数,因为这些天数经常变动。这可以通过使用窗口函数和提取理货表中生成的Date
值的一部分来实现。我已经包括了一系列不同的date
函数,如果您正在使用这个参考表,您可以使用这些函数作为示例,建议不要动态创建。但是,如果要创建静态表,最好只创建一次,然后手动整理特殊日期列表,以确保它们是正确的:
declare @StartDate date = '20100101';
declare @EndDate date = '20301231';
declare @MonthEndDay int = 7; -- Saturday
-- Tally table creates all the date values which can then be used as your date dimension.
with t(t) as(select t from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(t))
,d(d) as(select top(select datediff(d,@StartDate,@EndDate)+1) dateadd(d,row_number()over(order by (select null))-1,@StartDate)from t t1,t t2,t t3,t t4,t t5,t t6)
,c as(select d as FullDate
,case when month(d) = 12 -- This logic is to handle the final day of the year.
then case when day(d) = 31 then 1 else 0 end
else case when sum(case when datepart(weekday,dateadd(d,-1,d)) = @MonthEndDay then 1 else 0 end) over (partition by year(d) order by d) in(4,8,13,17,21,26,30,34,39,43,47,52)
and datepart(weekday,d) = @MonthEndDay
then 1
else 0
end
end as FiscalPeriodEndDate
,sum(case when datepart(weekday,dateadd(d,-1,d)) = @MonthEndDay then 1 else 0 end) over (partition by year(d) order by d) as WeekNum
,((sum(case when datepart(weekday,dateadd(d,-1,d)) = @MonthEndDay then 1 else 0 end) over (partition by year(d) order by d)-1) / 13)+1 as QuarterNum
from d
)
select FullDate
,FiscalPeriodEndDate
,WeekNum
-- Where there is a 53rd week it will show as the 5th Quarter per the calculation above, so change it to 4th.
,case when QuarterNum > 4 then 4 else QuarterNum end as QuarterNum
-- Examples of different date functions you can use to make querying and reporting easier and when indexed properly, a lot faster.
,year(FullDate) as DateYear
,month(FullDate) as DateMonth
,day(FullDate) as DateDay
,datepart(weekday,FullDate) as DateWeekDayNum
,datename(weekday,FullDate) as DateWeekDayName
from c
order by FullDate;
输出-请注意您的财务期间的FiscalPeriodEndDate
标志:
+------------+---------------------+---------+------------+----------+-----------+---------+----------------+-----------------+
| FullDate | FiscalPeriodEndDate | WeekNum | QuarterNum | DateYear | DateMonth | DateDay | DateWeekDayNum | DateWeekDayName |
+------------+---------------------+---------+------------+----------+-----------+---------+----------------+-----------------+
| ...etc | | | | | | | | |
| 2016-01-28 | 0 | 4 | 1 | 2016 | 1 | 28 | 5 | Thursday |
| 2016-01-29 | 0 | 4 | 1 | 2016 | 1 | 29 | 6 | Friday |
| 2016-01-30 | 1 | 4 | 1 | 2016 | 1 | 30 | 7 | Saturday |
| 2016-01-31 | 0 | 5 | 1 | 2016 | 1 | 31 | 1 | Sunday |
| 2016-02-01 | 0 | 5 | 1 | 2016 | 2 | 1 | 2 | Monday |
| ...etc | | | | | | | | |
| 2016-02-25 | 0 | 8 | 1 | 2016 | 2 | 25 | 5 | Thursday |
| 2016-02-26 | 0 | 8 | 1 | 2016 | 2 | 26 | 6 | Friday |
| 2016-02-27 | 1 | 8 | 1 | 2016 | 2 | 27 | 7 | Saturday |
| 2016-02-28 | 0 | 9 | 1 | 2016 | 2 | 28 | 1 | Sunday |
| 2016-02-29 | 0 | 9 | 1 | 2016 | 2 | 29 | 2 | Monday |
| ...etc | | | | | | | | |
+------------+---------------------+---------+------------+----------+-----------+---------+----------------+-----------------+
欢迎来到StackOverflow。请参加,学习提出好问题stackoverflow.com/help/how-to-ask,做一个回答。特别是要避免出现StackOverflow不是免费编码服务的上市要求的印象。为什么2017年4月1日3月底使用而不是2017年3月25日
?2017年6月1日<代码>与2017年6月24日<代码>相同?下个月我们可以走多远/我们必须离月底有多近?月底总是在最近的星期六,尽可能接近4-4-5模式。欢迎来到StackOverflow。请参加,学习提出好问题stackoverflow.com/help/how-to-ask,做一个回答。特别是要避免出现StackOverflow不是免费编码服务的上市要求的印象。为什么2017年4月1日3月底使用而不是2017年3月25日
?2017年6月1日<代码>与2017年6月24日<代码>相同?下个月我们可以走多远/我们必须离月底有多远?月底总是在最近的星期六,尽可能地适合4-4-5模式。戴夫,非常感谢你的帮助!非常感谢!我将为更广泛的社区发回任何更改。再次感谢!我试着添加以下内容来确定一年中的12个时期,但结果不一致。是否可以通过财政期间结束日期来识别每个期间?,(总和(当datepart(工作日,dateadd(d,-1,d))=@MonthEndDay然后1其他0结束时的情况)超过(按年份划分(d)按d排序)/3)+1FiscalPeriod@Nick你所说的12个周期是什么意思?简单地给它们编号?我是戴夫,非常感谢你的帮助!非常感谢!我将为更广泛的社区发回任何更改。再次感谢!我试着添加以下内容来确定一年中的12个时期,但结果不一致。是否可以通过财政期间结束日期来识别每个期间?,(总和(当datepart(工作日,dateadd(d,-1,d))=@MonthEndDay然后1其他0结束时的情况)超过(按年份划分(d)按d排序)/3)+1FiscalPeriod@Nick你所说的12个周期是什么意思?简单地给它们编号?