【发布时间】:2020-01-15 13:31:43
【问题描述】:
如上所述,我希望在我的数据集中创建一个列,说明日期范围内一年的百分比。
这已经在 excel 中完成,但我现在必须在 SQL 中重现它。以下是列数据类型:
- Yr1 int
- Yr2 浮动
- Yr3 浮动
- Yr4 浮动
- 期间开始日期时间
- 期间结束日期时间
- 期间指示器 varchar
- 闰年指示器 varchar
- 周期浮动的长度
- Yr1 赚取 % int
- Yr2 赚取 % 浮动
- 第三年赚取浮动百分比
- 第四年赚取浮动百分比
- 总收入百分比浮动
这是用于生成列的 SQL。不幸的是,Yr1 Earn % 不起作用。我收到一条错误消息:“操作数数据类型 datetime 对于除法运算符无效。”
有没有什么方法可以用下面的方式在 SQL 中计算这个??
,[Yr1]+1 as 'Yr2'
,[Yr2]+1 as 'Yr3'
,[Yr3]+1 as 'Yr4'
,dateadd(d,[INSRD PERIOD START],'1899-12-30') as 'Period Start'
,dateadd(d,[INSRD PERIOD END],'1899-12-30') as 'Period End'
,CASE WHEN MONTH([PERIOD START]) = MONTH([PERIOD END]) AND DAY([PERIOD START]) = DAY([PERIOD END])
THEN 'Y'
ELSE 'N'
END AS 'Period Indicator'
,CASE WHEN ISDATE(CAST(YEAR([Period Start]) AS char(4)) + '0229') = 1
OR
ISDATE(CAST(YEAR([Period End]) AS char(4)) + '0229') = 1
THEN 'Y'
ELSE 'N'
END as 'Leap Year Indicator'
,(([Period End]-([Period Start]-CASE WHEN [Period Indicator]='Y'
THEN 0
ELSE 1
END)))/(CASE WHEN [Leap Year Indicator]='N'
THEN 365
ELSE 366
END) as 'Length of Period'
,(SELECT MAX(v)
FROM (VALUES (0),
(((SELECT MIN(w)
FROM (VALUES ('2019-06-30'),
(CASE WHEN [Period Indicator]='N'
THEN DATEADD(d,[Period End],'1899-12-30')
ELSE (DATEADD(DAY,-1,[Period End]))
END)
,
(DATEFROMPARTS([Yr1],'12','31'))
) as value(w))-
(SELECT MAX(x)
FROM (VALUES (DATEFROMPARTS([Yr1],'12','31')),
(DATEADD(DAY,-1,[Period Start]))
) as value(x)
)
)/((CASE WHEN [Period Indicator]='N'
THEN dateadd(DAY,[Period End],'1899-12-30')
ELSE DATEADD(DAY,-1,[Period End])
END)
- (DATEADD(DAY,-1,[Period Start]))))
) as value(v)
) as 'Yr1 Earn %'
,[Yr2 Earn %] as 'Yr2 Earn %'
,[Yr3 Earn %] as 'Yr3 Earn %'
,[Yr4 Earn %] as 'Yr4 Earn %'
,[Yr1 Earn %]+[Yr2 Earn %]+[Yr3 Earn %]+[Yr4 Earn %] as 'Total Earn %'
编辑:这是用于在屏幕截图中生成 Yr1 Earn % 列的 excel 公式的副本。 z_eval='2019-06-30'
=MAX(0,(MIN(z_eval,IF($G2="N",$F2,$F2-1),DATE(A2,12,31))-MAX(DATE(A2->1, 12,31),$E2-1))/(IF($G2="N",$F2,$F2-1)-($E2-1))))
编辑:感谢大家迄今为止对 cmets 的帮助。我使用Yr1 Earn % 的这段代码将所有dates 转换为ints。所有值都默认为零。外部 MAX(v) 函数是否难以解析内部 Max/Min 函数?
,(SELECT MAX(v) FROM (VALUES (0), (((SELECT MIN(w) FROM (VALUES (DATEDIFF(d,'1899-12-30','2019-06-30')), (CASE WHEN [Period Indicator]='N' THEN DATEDIFF(d,'1899-12-30',[Period End]) ELSE (DATEDIFF(d,'1899-12-30',DATEADD(DAY,-1,[Period End]))) END) , (DATEDIFF(d,'1899-12-30',DATEFROMPARTS([Yr1],'12','31'))) ) as value(w))- (SELECT MAX(x) FROM (VALUES (DATEDIFF(d,'1899-12-30',DATEFROMPARTS([Yr1],'12','31'))), (DATEDIFF(d,'1899-12-30',DATEADD(DAY,-1,[Period Start]))) ) as value(x) ) )/((CASE WHEN [Period Indicator]='N' THEN DATEDIFF(d,'1899-12-30',DATEADD(DAY,[Period End],'1899-12-30')) ELSE DATEDIFF(d,'1899-12-30',DATEADD(DAY,-1,[Period End])) END) - (DATEDIFF(d,'1899-12-30',DATEADD(DAY,-1,[Period Start]))))) ) as value(v) ) as 'Yr1 Earn %'
【问题讨论】:
-
DATEDIFF是你的朋友。顺便说一句,这也可以用来确定一年中的天数(如果是闰年,则间接确定,而不是相反)。 -
如果您使用a Calendar table,这是一个简单的百分比计算。在 Date 上加入 Calendar 表,并计算范围内的日期数除以一年中的天数。
-
@Jeroen DATEDIFF 会很棒,但我的公式需要除法。 SQL 不允许我划分日期。我试过强制转换为 int 无济于事。
-
确实,它不能划分日期,但
DATEDIFF以INT的形式为您提供任何所需时间段内两个日期之间的差异,而这些日期确实可以划分。 Excel 将日期处理为代表天数加上分数的数字有点不稳定,并且可能难以转换为差异语义,但它总是可行的。 (只是不要让我当场做。) -
另一种方法仅显示一年中的完成百分比:
=A1-DATE(YEAR(A1),1,0)将显示一年中的第 # 天,除以 365(或 366 表示飞跃)得出一年的完成百分比。
标签: sql-server excel tsql