几年前我在一家电信公司工作,我必须根据以下算法生成一个计算呼叫持续时间的公式:
如果RCT小于t1,则CD等于t1
如果RCT大于t1,则CD = t1 + x * t2,其中x将“RCT”“舍入”到t2的下一个最大倍数。
此算法转换为:“第一个t1秒充电,然后每隔t2秒充电一次”。
示例:
t1 t2 RCT CD
60 10 48 60
60 10 65 70
60 10 121 130
30 20 25 30
30 20 35 50
30 20 65 70
你能创建一个能够返回“呼叫持续时间”CD的函数/ SQL吗?
不使用if then else ......?
答案 0 :(得分:4)
假设int列:
SELECT t1
,t2
,RCT
CASE
WHEN RCT < t1
THEN t1
ELSE
t1 + t2 * ((RCT - t1) / t2 + SIGN((RCT - t1) % t2))
END AS CD
但我想还有一个案例,让我看看能否摆脱它。
仅使用整数运算(仍然不是ANSI):
SELECT t1
,t2
,RCT
,CD
,t1 + SIGN(RCT / t1) * t2 * ((RCT - t1) / t2 + SIGN((RCT - t1) % t2)) AS CalcCD
FROM Calls
答案 1 :(得分:2)
编辑:进一步简化,并修复&lt; vs&lt; =错误。
没有浮点并且可以访问我有权访问的每个数据库:
create table calls (t1 int, t2 int, rct int, cd int)
insert into calls (t1, t2, rct, cd)
values (60, 10, 48, 60)
insert into calls (t1, t2, rct, cd)
values (60, 10, 65, 70)
insert into calls (t1, t2, rct, cd)
values (60, 10, 121, 130)
insert into calls (t1, t2, rct, cd)
values (30, 20, 25, 30)
insert into calls (t1, t2, rct, cd)
values (30, 20, 35, 50)
insert into calls (t1, t2, rct, cd)
values (30, 20, 65, 70)
--Additional test to show that it works
insert into calls (t1, t2, rct, cd)
values (60, 10, 70, 70)
select t1, t2, rct, cd,
t1 + case when rct <= t1
then 0
else ( (rct-1-t1) / t2 + 1) * t2 end as CalceCD
from calls
结果:
t1 t2 rct cd CalceCD ----------- ----------- ----------- ----------- ----------- 60 10 48 60 60 60 10 65 70 70 60 10 121 130 130 30 20 25 30 30 30 20 35 50 50 30 20 65 70 70 60 10 70 70 70 (6 row(s) affected)
您可以自由地将该函数创建为UDF或您的SQL环境允许清理选择的任何内容。
编辑:是,楼层和偏移量为1可以避免浮动数学。
答案 2 :(得分:2)
我会用:
t1 + t2*ceiling( (rct - t1 + abs(rct - t1))*1.00/(2*t2) )
或者:
t1 + t2*ceiling( Cast((rct - t1 + abs(rct - t1)) as float)/(2*t2) )