【问题标题】:database/algorithm for a rate structure速率结构的数据库/算法
【发布时间】:2010-01-21 14:29:24
【问题描述】:

我必须按照以下方式根据费率结构计算价格:

$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

我对设置数据库结构和算法(更大的症结点)来计算这个有点迷茫。有没有人这样做过?有没有一种很好的、​​优雅的方法来计算这类事情?

编辑: 例如,运行 25,100 个单位的前 500 个单位的成本为 303.00 美元,接下来的 9,500 个单位的成本为 218.50 美元,接下来的 15,000 个单位的成本为 330.00 美元,接下来的 100 个单位的成本为 2.10 美元,总计 853.60 美元。

不会是一个简单的 25,100 * $0.021 计算 - 我很清楚如何选择和计算它。

类似于所得税的评估方式 - 在边际基础上。

【问题讨论】:

  • 不,这是用于工作的内部系统。

标签: php mysql algorithm


【解决方案1】:

我假设您想要一些灵活的东西,否则硬编码将是微不足道的。

您可以使用定价表:

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

那么你可以计算如下:

$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'];
}

我假设您需要 PHP 中的算法。

【讨论】:

  • 我没有想过用“自上次价格点以来的数量”而不是“自 0 以来的数量”来表达单位数。试一试,谢谢!
【解决方案2】:

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

【讨论】:

  • 这是让我陷入困境的边际计算。我不能只做这么简单的事情。例如,运行 25,100 个单位的前 500 个单位的成本为 303.00 美元,接下来的 9,500 个单位的成本为 218.50 美元,接下来的 15,000 个单位的成本为 330.00 美元,接下来的 100 个单位的成本为 2.10 美元。
  • 从您的原始问题中并不太清楚,也不是计算数量折扣的“正常”方式。你的仍然在不同的乐队。
  • 你没有这么说,我也认为如果订单超过 10k,每个 单位是 0.022 美元。不过,我会给你一个提示:前 10k 的价格总是相同的,无论他们订购的是 10,001 件还是 100,000 件。
  • 另外,请不要仅仅因为您的问题不清楚就给出每个答案-1,那只是不礼貌。
  • @S.Lott 感谢您的编辑,但这个答案仍然没有考虑边际利率结构。我需要计算超出每个价格步进点的单位,我想知道是否有比蛮力更优雅的方法。
【解决方案3】:

类似这样的:

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


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

因此,产品和价格之间存在一对多的关系。如果您需要统一费率而不考虑数量,则可以使用标记值作为最大值。

【讨论】:

  • 这并没有考虑到固定价格和单价,而更多的是我正在努力解决的数据库结果的计算。
【解决方案4】:
SELECT 
 CASE is_fixed_price
  WHEN 1
   THEN unit_price / ?  
  ELSE
   unit_price
  END
FROM rate_structure
WHERE ? BETWEEN min_qty AND max_qty

在哪里?是您的客户想要订购的数量。对于 mysql 5.x,我脑海中浮现的语法。这样做的副作用是潜在的舍入误差累积。

【讨论】:

  • 除非我对这里的语法有误解,否则这似乎是在单个价格点进行非边际计算。
  • 哦,我的错;您指定的边际成本对我来说没有意义-通常(在单个抽象业务的背景下)单位成本会随着数量的增加而下降而不是上升。我认为在您的情况下,无论您订购 1 个单位还是 500 个单位,最低付款都是 300 美元。事实并非如此,而且我的代码不正确。但是,您仍然可以使用我向您展示的条件进行计算。
【解决方案5】:

我最后做了什么:

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;
}

【讨论】:

    猜你喜欢
    • 2012-04-18
    • 2012-04-27
    • 1970-01-01
    • 2015-09-02
    • 2012-02-25
    • 2011-06-08
    • 1970-01-01
    • 2015-05-09
    • 2010-09-21
    相关资源
    最近更新 更多