2010-01-21 4 views
5

ich auf einer Tarifstruktur entlang dieser Linien einen Preis zu berechnen haben:Datenbank/Algorithmus für eine Tarifstruktur

$303.00 fixed price up to 500 units 
$0.023 additional per unit from 501-10,000 units 
$0.022 additional per unit from 10,001-25,000 units 
$0.021 additional per unit from 25,001-50,000 units 

Ich bin ein wenig eine Datenbank auf Einstellung Struktur und Algorithmus (der größere Knack verloren up Punkt), um dies zu berechnen. Hat jemand das getan? Gibt es eine schöne, elegante Art, so etwas zu berechnen?

edit: Als Beispiel eine 25.100-Einheit laufen würde $ 303,00 für die ersten 500 Einheiten, kostet $ 218,50 für die nächsten 9.500 Einheiten, $ 330.00 für die nächsten 15.000 Einheiten und $ 2.10 für die nächsten 100 Einheiten für insgesamt von 853,60 $.

Es wäre nicht eine einfache 25,100 * $ 0,021 Berechnung sein - ich bin mir bewusst, wie man das wählt und berechnet.

Ähnlich wie die Einkommensteuer wird - auf einer marginalen Basis beurteilt.

+0

diese Hausaufgaben? –

+0

Nein, es ist für ein internes System bei der Arbeit. – ceejayoz

Antwort

-1

Was ich tun liquidiert:

size units  fixed  per 
1  500 303.000 0.000 
1  10000  0.000 0.023 
1  25000  0.000 0.022 
1  50000  0.000 0.021 



function calculate_price($size, $quantity) { 
    global $db; 

    $price = 0; 
    $count = 0; 

    // fetch rates from the database 
    // note: $size is already sanitised by the calling function 
    $query = "SELECT units, flat, per FROM rates WHERE size={$size} ORDER BY units ASC"; 
    $result = $db->query($query); 

    // step through the rates 
    while($rate = $result->fetch_object()) { 
    // figure out how many of our units fall within this tier 
    $tier_count = max(0, min($quantity - $count, $rate->units - $count)); 

    // calculate the price for this tier, including any flat rate 
    $tier_price = $rate->flat + ($rate->per * $tier_count); 

    // add tier price and count to the totals 
    $price += $tier_price; 
    $count += $tier_count; 

    // store the last, largest number of units rate for any leftovers outside our tiers 
    $last_rate = $rate; 
    } 

    // if some of our units fall outside our defined tiers, use the last tier's values for them 
    if($count < $quantity) { 
    $tier_count = $quantity - $count; 
    $tier_price = $last_rate->flat + ($last_rate->per * $tier_count); 
    $price += $tier_price; 
    $count += $tier_count; 
    } 

    return $price; 
} 
0

Etwas wie folgt aus:

Product 
------- 
[PK] ProductID 


Price 
----- 
[PK] PriceID 
[FK] ProductID 
Price 
QtyMin 
QtyMax 

So effektiv eine 1-Beziehung zwischen Produkt und Preis. Sie können einen Sentinel-Wert für das Maximum verwenden, wenn Sie unabhängig von der Menge eine Pauschale benötigen.

+0

Das bedeutet nicht, dass es sowohl einen festen Preis als auch einen Stückpreis gibt, und es ist mehr die Berechnung aus den Datenbankergebnissen, mit denen ich mich abmühen muss. – ceejayoz

3

Python

from collections import namedtuple 

RateRule= namedtuple('RateRule', ['qty_band','fixed','per_unit'])  

rate_table = [ 
    RateRule(500, 303, None), 
    RateRule(9500, None, 0.023), 
    RateRule(15000, None, 0.022), 
    RateRule(25000, None, 0.021) 
] 

def total_price(units, rate_table): 
    # Base 
    total = rate_table[0].fixed 
    units_purchased_so_far = rate_table[0].qty_band 
    # Whole Price Bands 
    rule = 1 
    while units > units_purchased_so_far + rate_table[rule].qty_band: 
     total += rate_table[rule].qty_band * rate_table[rule].per_unit 
     units_purchased_so_far += rate_table[rule].qty_band 
     rule += 1 
    # Units within the top Price Band 
    if units > units_purchased_so_far: 
     total += (units - units_purchased_so_far) * rate_table[rule].per_unit 
    return total 
+0

Es ist die marginale Berechnung, die mich für eine Schleife wirft. Ich kann nicht einfach so etwas tun. Zum Beispiel würde ein 25.100 Einheitenlauf $ 303.00 für die ersten 500 Einheiten, $ 218.50 für die nächsten 9.500 Einheiten, $ 330.00 für die nächsten 15.000 Einheiten und $ 2.10 für die nächsten 100 Einheiten kosten. – ceejayoz

+0

Das ist nicht ganz klar aus Ihrer ursprünglichen Frage und nicht die "normale" Art, wie Mengenrabatte berechnet werden. Deine sind immer noch in verschiedenen Bands. –

+0

Das hast du nicht gesagt, ich dachte auch, es wäre 0,022 $ für jede * Einheit, wenn die Bestellung über 10k wäre. Ich gebe dir einen Tipp: Die ersten 10k kosten immer den gleichen Preis, egal ob sie 10.001 oder 100.000 Einheiten bestellen. –

0
SELECT 
CASE is_fixed_price 
    WHEN 1 
    THEN unit_price/? 
    ELSE 
    unit_price 
    END 
FROM rate_structure 
WHERE ? BETWEEN min_qty AND max_qty 

Wo? ist die Menge, die Ihr Kunde bestellen möchte. Syntax aus dem Kopf, für mysql 5.x. Die Nebenwirkung davon ist eine potentielle Rundungsfehlerakkumulation.

+0

Wenn ich etwas in der Syntax hier nicht falsch verstehe, scheint dies eine nicht-marginale Berechnung zu einem einzigen Preispunkt zu sein. – ceejayoz

+0

Oh, mein Schlechter; die Grenzkosten, wie Sie angegeben haben, ergeben für mich keinen Sinn - typischerweise (im Kontext eines einzelnen abstrakten Geschäfts) sinken die Stückkosten und nicht, wenn die Menge erhöht wird. Ich dachte, dass in Ihrem Szenario minimale Zahlung $ 300 ist, ob Sie 1 Einheit oder 500 bestellen. Es ist nicht und mein Code ist falsch. Sie können jedoch weiterhin die Bedingungen verwenden, da ich Ihnen gezeigt habe, dass Sie die Berechnungen so durchführen können, wie Sie möchten. – mst

3

Ich nehme an, Sie wollen etwas flexibles, sonst wäre es trivial, es hart zu codieren.

Sie könnten eine Preistabelle verwenden:

ID MAX FIX UNIT 
1 500 303 0 
2 9500 0  .23 
3 15000 0  .22 
4 25000 0  .21 

berechnen Sie könnten dann wie folgt:

$items = ?; 
$cost = 0; 
$rows = get_rows("select max, fix, unit from pricing order by id asc"); 
foreach ($rows as $r) 
{ 
    if ($items <= 0) 
     break; 
    $cost += $r['fix'] + min($r['max'], $items) * $r['unit']; 
    $items -= $r['max']; 
} 

ich angenommen haben, dass Sie den Algorithmus in PHP wollen.

+0

Ich hatte nicht daran gedacht, die Anzahl der Einheiten in "Anzahl seit letztem Preispunkt" anstelle von "Anzahl seit 0" auszudrücken. Werde dies versuchen, danke! – ceejayoz