sql用于收费的滑动率卡

时间:2013-10-31 00:55:04

标签: sql

我有一张滑动(按比例)价目表,我需要向其收取费用,我想知道最好的设计。例如,我的价目表是这样的:

(用法是整数而非浮点数)。

Level    Usage    Rate
----------------------
0        10,000   $2.00
0        20,000   $1.00
0        30,000   $0.50
1        10,000   $4.00
1        20,000   $2.00
1        30,000   $1.00

因此,例如,如果客户使用15,000个小部件处于0级,则会收取费用:

10,000 * 2.00 = $20,000
 5,000 * 1.00 = $ 5,000
-----------------------
Total:          $25,000

注意,对于小部件在1-10,000之间,小部件的收费为2.00美元/小部件,然后在10,001-20,000之间的小部件为$ 1.00 /小部件,依此类推。也就是说,他们以最便宜的价格为所有小部件收取费用 - “早期”的小部件更贵,然后小部件的数量越多越便宜。

我在考虑预先计算费用,因此我可以在客户和计算费率之间进行联接。显然,表 pre_calc 会很大,但磁盘空间很便宜。而且每次计算成本都会更快/更容易。

Table pre_calc
==============

Level    Usage    Cost
----------------------
0            0    $0
0            1    $2.00
0            2    $4.00
... etc
1            0    $0
1            1    $4.00
1            2    $8.00
... etc

允许我这样做

SELECT c.name, p.cost
FROM customers as c
INNER JOIN pre_calc as p
ON c.level = p.level AND c.usage = p.usage;

对此设计有何评论?有没有更好的方法呢?

2 个答案:

答案 0 :(得分:1)

这样的事情怎么样?

level low     high       price

0     0       10000      20000
0     10000   20000      10000
0     20000   30000      5000

然后是SQL:

select sum(p) from (
  select case 
    when $value$ > high 
      then price 
      else ($value$ - low) / (high - low) * price 
    end as p
  from ...
  where $value$ < high
)

答案 1 :(得分:1)

此查询应与您现有的表结构一起使用。它比预先计算的查询稍微复杂一些,但另一方面,当速率发生变化时,它不会使用需要为每个使用int值更新的预先计算的表。我的猜测是,这里的表现会比你预先计算的更差,但你只会确定你是否测试过它。

SELECT c.name,
    -- The usage rates less than or equal to the customer's usage
    (SELECT SUM(r.Rate * r.Usage)
     FROM Rates r 
     WHERE r.Level = c.Level and r.Usage <= c.Usage) +
    -- The rate from the usage rate immediately above the customer's level
    -- using the usage top limit from the rate immediately less or equal to the customer's usage
    (SELECT TOP 1 r2.Rate * (c.Usage - (SELECT TOP 1 r3.Usage FROM Rates r3 
                                        WHERE r3.Level = c.Level and r3.Usage <= c.Usage
                                        ORDER BY Usage DESC))
     FROM Rates r2
     WHERE r2.Level = c.Level and r2.Usage > c.Usage
     ORDER BY Usage ASC) as cost
FROM customers as c