2009-01-30 21 views
7

Ich wurde vor einigen Jahren für ein Telekommunikationsunternehmen arbeiten, und ich hatte eine Formel zu erzeugen, die den folgenden Algorithmus nach Dauer eines Anruf berechnet:Mathematische Formel Gesprächsdauer für die Berechnung

  • t1 ist die erste Periode
  • t2 ist die Wiederholungsperiode
  • RCT die tatsächliche Anrufzeit (in Sekunden)
  • CD Dauer (für Abrechnungszwecke) ist die effektive Aufruf
ist

Wenn RCT kleiner als t1 ist, dann ist die CD gleich t1
Wenn RCT größer als t1 ist, dann CD = t1 + x * t2, wobei x RCT auf das nächsthöchste Vielfache von t2 "rundet".

Dieser Algorithmus wird wie folgt übersetzt: "Lade die ersten t1 Sekunden auf, lade danach alle t2 Sekunden auf".

Beispiel:

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 

Können Sie eine Funktion/SQL erstellen, die die "Gesprächsdauer" CD zurückkehren wird?

Ohne zu verwenden wenn dann sonst ...?

Antwort

2

EDIT: weiter vereinfacht und behoben < vs < = Fehler.

Kein Floating-Point und arbeitete an jede Datenbank Ich habe Zugang zu:

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 

Ergebnis:

 
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) 

Sie wäre frei, die Funktion als UDF oder was auch immer Ihre SQL-Umgebung erstellen können um die Auswahl zu bereinigen.

Edit: Ja, Boden und ein Offset von 1 vermeidet floating math.

+0

Sollte das nicht sein 'Decke ((RCT -t1)/t2) 'statt' (floor ((rct-t1)/t2) +1) '? Andernfalls würde 60-10-70 eine CD von 80 produzieren. –

+0

einfügen in Anrufe Werte (60, 10, 70, 70) einfügen in Anrufe Werte (60, 10, 80, 80) Diese funktionieren nicht –

+0

Diese Einfügungen nehmen eine Syntax an, die das Format der Tabelle implizieren kann. Fügen Sie bei Bedarf die (t1, t2, rct, cd) hinzu. – Godeke

4

Unter der Annahme, int Spalten:

SELECT t1 
    ,t2 
    ,RCT 
    CASE 
    WHEN RCT < t1 
     THEN t1 
    ELSE 
     t1 + t2 * ((RCT - t1)/t2 + SIGN((RCT - t1) % t2)) 
    END AS CD 

Aber ich denke, es gibt noch ein Fall ist, lassen Sie mich sehen, ob ich es loswerden kann.

Mit nur Integer-Arithmetik (noch nicht ANSI):

SELECT t1 
     ,t2 
     ,RCT 
     ,CD 
     ,t1 + SIGN(RCT/t1) * t2 * ((RCT - t1)/t2 + SIGN((RCT - t1) % t2)) AS CalcCD 
FROM Calls 
+0

Schöne Lösung! +1 –

+0

Danke, es ist immer noch chaotischer als ich denke, dass es sein kann. Mit der Umstellung auf float ist es sauberer, aber ich wette messbar langsamer für BIG-Abfragen (wie Telefonanrufe!). –

+0

Ah gut. Keine Notwendigkeit für vorzeitige Optimierung :) Wenn das OP es benötigt, um zehn Milliarden Einträge in weniger als einer Sekunde zu berechnen, muss er eine weitere Frage stellen, wie die Effizienz verbessert werden kann! –

2

würde ich verwenden:

t1 + t2*ceiling((rct - t1 + abs(rct - t1))*1.00/(2*t2)) 

Oder:

t1 + t2*ceiling(Cast((rct - t1 + abs(rct - t1)) as float)/(2*t2)) 
+0

Ihnen fehlt eine öffnende Klammer. –

+0

Vielen Dank, ich habe es gerade bemerkt :) –

+0

Ich habe versucht, ein in einigen Orten, aber ich bekomme keine Ergebnisse, die übereinstimmen. –

Verwandte Themen