范围与查找的邮政编码列表?

时间:2012-06-28 08:03:02

标签: mysql sql

对于购物车,我想建立一个邮政编码数据库,我的运营商可以在这里发货。

我可能有几家运营商,所以我正在寻找灵活的解决方案。有两种付款方式 - 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%),鳕鱼邮政编码缩小至842(30%)。

设计#2

cod_zipcodes
    zipcode(int)

prepaid_zipcodes
    zipcode(int)

基本上这个设计只是按原样列出。如果有多个载波我合并列表。所以我丢失了运营商为特定邮政编码发货的信息。但这不是问题(但如果它被整理出来,那也不是问题!)。我只想查找数据库,客户输入的邮政编码在我们允许的列表中。

我对实时数据库的经验有限。请说明哪种设计更好,或建议您自己设计。

谢谢!

1 个答案:

答案 0 :(得分:1)

第一种设计可能是最紧凑的;可以通过在startend上添加生成索引来优化它。您还可以将两种付款方式组合在一起:

zipcodes
    start(int) | end(int) | carrier(fk::carried.id) | cod (0, 1) | prepaid (0, 1)

carrier字段是可选字段,但稍后当您需要更新一个运营商的邮政编码范围时,可以使用它。

根据codprepaid是否可用,不要试图聪明并将范围合并在一起;您可以输入具有不同承运人和付款类型可用性的多个范围。要查询它们,您将使用:

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字段,因此这意味着您必须编写一个脚本来检测特定邮政编码的添加,删除和更新,或者重新开始完全与两个载体数据。


如果更新很少见,并且您不介意在发生这种情况时将整个表格放下,我会推荐第二个选项。通过在每行中添加codprepaid类型而不是两个单独的表,与范围解决方案相比,您可以使用主键来加快查找速度。

如果您喜欢灵活性以及您可以确定特定范围内支持哪个运营商的事实,我会选择第一个选项;对于大多数情况,索引仍然足够快,表格大小可能与第二种选择相当。