对于购物车,我想建立一个邮政编码的数据库,我的承运商可以在那里发货。
我可能有几个运营商,所以我正在寻找一个灵活的解决方案。有两种支付方式--COD(现金)和预付(网上银行)。
其中一个承运商的发货邮政编码列表中有2,775个用于COD方法的条目,以及4,139个用于预付费的条目。
设计#1 (多亏了这个answer)
我将直接列表转换为范围(如{1,2,3,5,8,9} => {(1,3),(5,5),(8,9)}),并具有模式-
carrier
id(int) | name (varchar)
cod_zipcodes
start(int) | end(int) | carrier(fk::carrier.id)
prepaid_zipcodes
start(int) | end(int) | carrier(fk::carrier.id)在转换为范围时,预付费邮政编码缩小到1,593(38%),cod邮政编码缩小到842(30%)。
设计#2
cod_zipcodes
zipcode(int)
prepaid_zipcodes
zipcode(int)基本上,这个设计只有一个列表。如果有多个运营商,我会合并列表。因此,我丢失了特定邮政编码的承运商发货的信息。但是这不是问题(但是如果它被解决了,那也不是问题!)我只想查找数据库,由客户输入的邮政编码在我们的允许列表中。
我对实时数据库的经验有限。请指出哪种设计更好,或建议您自己的设计。
谢谢!
发布于 2012-06-28 16:27:14
第一种设计可能是最紧凑的;可以通过在start和end上添加跨越索引来对其进行优化。您也可以像这样组合这两种付款类型:
zipcodes
start(int) | end(int) | carrier(fk::carried.id) | cod (0, 1) | prepaid (0, 1)carrier字段是可选的,不过您可以在以后需要更新某个运营商的邮政编码范围时使用它。
不要试图聪明地根据cod和prepaid是否可用而将范围合并在一起;您可以输入具有不同运营商和支付类型可用性的多个范围。要查询它们,您可以使用:
SELECT COUNT(cod), COUNT(prepaid)
FROM zipcodes
WHERE start <= :start AND :end <= end这将给出一行,其中包含特定邮政编码的cod和/或prepaid的可用性(即使它可能匹配多个数据库行。
当运营商更改其邮政编码范围和支付可用性时,最简单的方法是删除该运营商的所有行并重新填充(使用表锁);如果您决定保留该数据库字段,这对您来说非常容易。
你的第二个设计看起来更像是你从运营商那里接收邮政编码列表的方式,而且管理也更加简单。不过,我会再次将它们放在一个表中:
zipcodes
zipcode | cod (0, 1) | prepaid(0, 1)通过选择ENUM数据类型,您也可以获得非常好的数据压缩效果。当承运商更改其递送数据时,更新此表就不那么简单了,因为缺少carrier字段,因此这意味着您必须编写一个脚本来检测特定邮政编码的添加、删除和更新,或者完全使用两个承运商数据重新开始。
如果更新很少,并且您不介意在发生更新时删除整个表,我建议使用第二种方法。通过在每一行中添加cod和prepaid类型,而不是在两个单独的表中添加,您可以使用主键来实现比范围解决方案更快的查找。
如果您喜欢灵活性,并且您可以分辨出在特定范围内支持哪个载体,我会选择第一个选项;对于大多数情况,索引仍然足够快,并且表大小可能与第二个选项相当。
https://stackoverflow.com/questions/11240436
复制相似问题