Математическая формула для расчета продолжительности звонка - PullRequest
7 голосов
/ 31 января 2009

Я работал в телекоммуникационной компании несколько лет назад, и мне пришлось сгенерировать формулу, которая рассчитывает продолжительность звонка по следующему алгоритму:

  • t1 - первый период
  • t2 - повторяющийся период
  • RCT - фактическое время звонка (в секундах)
  • CD - эффективная продолжительность звонка (для выставления счетов)

если 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

Можете ли вы создать функцию / SQL, которая будет возвращать компакт-диск "длительность вызова"?

Без использования if then else ...?

Ответы [ 3 ]

4 голосов
/ 31 января 2009

Предполагая 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
2 голосов
/ 31 января 2009

Я бы использовал:

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) )
2 голосов
/ 31 января 2009

РЕДАКТИРОВАТЬ: далее упрощено, исправлено

Нет плавающей запятой и работал на каждой базе данных, к которой у меня есть доступ:

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 позволяет очистить.

Редактировать: да, пол и смещение в единицу избегают плавающей математики.

...