我有一张滑动(按比例)价目表,我需要向其收取费用,我想知道最好的设计。例如,我的价目表是这样的:
(用法是整数而非浮点数)。
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;
对此设计有何评论?有没有更好的方法呢?
答案 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