65

给定在关系表中存储国际地理地址的任务,最灵活的模式是什么?地址的每一部分应该分解成各自的字段,还是应该更像自由文本?

将不同格式的地址分成不同的表有什么意义吗?例如,有一个 USAAddress、CanadianAddress、UKAddress... 的表?

4

9 回答 9

106

我将从我的博客文章中总结我的想法——地址存储课程(在 archive.org 上)。

在我当前的项目中[我在一家物流公司工作],我们正在存储国际地址。在设计这部分数据库时,我对世界各地的地址进行了研究。有很多不同的格式。在西方世界,我们倾向于使用相当统一的格式——有一些差异,但主要是:

  • 街道号码- 数字
  • 房屋或建筑物名称- [VarChar - 在英国,一些房屋/建筑物是按名称而非编号识别的]
  • 街道号码后缀[VarChar,尽管在大多数情况下,Char(1) 就足够了]
    • 甲、乙等
  • 街道名称[VarChar]
  • 街道类型[如果您有 StreetTypes 表,则为 VarChar 或 Int]
    • 到目前为止,我在英语世界中发现了 262 种独特的类型,可能还有更多,别忘了还有其他语言,例如 Strasse、Rue 等。
  • 街道方向[VarChar(2)]
    • N、E、S、W、NE、SE、NW、SW
  • 地址类型[如果您有 AddressTypes 表,则为 VarChar 或 Int]
    • 邮政信箱
    • 公寓
    • 建造
    • 地面
    • 办公室
    • 套房
    • ETC...
  • 地址类型标识符[VarChar]
    • ie Box Number, Apartment Number, Floor Number 记住公寓号码和办公室有时有字母数字信息 - 比如 1A
  • Local Municipality [VarChar 或 Int,如果你有一个 Municipalities 表]
    • 例如,如果您的小村庄/村庄出现在城镇之前的地址中。
  • City/Town [如果您有 Cities 表,则为 VarChar 或 Int]
  • Governing District [VarChar 或 Int,如果您有 Districts 表]
    • 州(美国)
    • 省(加拿大)
    • 联邦区(墨西哥)
    • 县(英国)
    • ETC...
  • 邮政区[VarChar]
    • 邮编(美国)
    • 邮政编码(加拿大、墨西哥)
    • 邮政编码(英国)
  • Country [VarChar 或 Int,如果你有 Country 表]

这似乎涵盖了大多数国家/地区,但字段的顺序可能会有所不同。您可以在http://www.bitboost.com/ref/international-address-formats.html#Formats找到显示格式列表

例如,在许多国家/地区,邮政编码位于城市名称之前,街道编号位于街道名称之后。在加拿大、美国和英国,街道编号位于街道名称之前,邮政编码(或 ZIP)位于城市名称之后。

在回答您关于将地址分隔到不同国家/地区的问题时,我不建议这样做,它只会让其他领域的生活变得更加困难 - 例如报告。我提供的格式涵盖了我们物流数据库中的所有地址,该数据库涵盖美国、加拿大、墨西哥和英国,没有任何问题。它还涵盖了我们所有的欧洲、中国、日本和马来西亚地址。我不能代表其他国家/地区发言,但我还没有存储这些字段不支持的国家/地区的地址。

我不建议使用其他人建议并在许多数据库中看到的 Address1、Address2、Address3 格式,因为从字母数字字符串中解析地址信息并不像最初看起来那么简单——尤其是在数据输入不正确的情况下, 由于错误信息、拼写错误、拼写错误等。如果您分开您的字段,您可以使用距离算法来检查可能的含义,使用概率来检查街道名称与邮政编码和街道号码或检查省份和城市与街道名称等。尝试当您有一个字符串表示您的整个街道地址时,请执行任何操作。无论如何,这都不是一件小事。

地址数据库上的 QA 是一个令人头疼的问题。在这方面简化您的生活的最简单方法是确保所有字段仅包含一条信息,该信息可以在输入时自动验证为正确。概率、距离算法和正则表达式可以检查输入的有效性,并向用户提供关于他们的错误是什么的反馈,并提出适当的更正建议。

需要注意的一个警告是名称也是街道类型的道路 - 如果您覆盖加拿大,您需要注意多伦多的“Avenue Road”,如果您使用的是 Address1, 2,这会让您大吃一惊, 3 格式。这可能也发生在其他地方,虽然我不知道它们 - 一个实例就足以让我尖叫 WTF?!

于 2009-07-21T15:42:31.350 回答
26

注意不要过度分析地址格式。当你这样做时,你很可能最终得到一个大多数用户需要解决的规范,有效地迫使他们使用错误的字段,或者只填写主要字段而忽略额外的字段。

保持简单。

当您开始使用不同于孤立语言(如英语或西班牙语)的语言时,像 BenAlabaster 提到的 StreetType 会导致问题。

向您展示在野外的情况有多糟糕:阿姆斯特丹的“Henriette Roland Holststraat”,由“Henriette”+“Roland Holst”+“straat”组成,可以缩写为“Roland Holststraat”,或“ Roland Holststr.”,或拼写错误为“HRHolststr”。或“Henriette Roland-Holst straat”,视天气而定。除非你有地球上每个国家的最新街道登记册,否则你将无处可去。

最后,请注意在某些多语言国家/地区,名称可能因一种语言而异!例如在布鲁塞尔,许多街道都有法语荷兰语名称:“Avenu du Port”和“Havenlaan”,具体取决于收件人的首选语言。(为了安全起见,谷歌地图会交替显示两个名字。)

您可以在这里尝试设计各种巧妙的技巧,但都是销售代表。会明白这一点吗?

于 2009-07-23T16:51:18.430 回答
8

这取决于你想用它做什么。

我发现如果将地址分开用于其他目的(例如根据 USPS 数据验证或从 UPS/FEDEX 获取运费),总是更容易使用它们。

以下是我通常用于地址的内容:

  • 地址第一行
  • 地址行 2
  • 地址行 3
  • 城市
  • 地区
  • 邮政编码
  • 国家

回应编辑: 在大多数情况下,我看不到使用。我上面列出的表格对于大多数国家的地址都有足够的字段(并且足够通用)。

于 2009-07-21T15:06:05.447 回答
8

对于偶然发现这个问题的人来说,这是一个轶事:

我作为一个在许多大洲(欧洲、亚洲、北美)生活和工作过的人发言。根据我的经验以及与我一起工作的人的经验,我们使用执行以下操作的系统要容易得多:

  1. 提供三行,我将在其中键入一个地址。当我逐字输入这三行时,将它们传递给您当地的邮政服务。让我使用我想要的任何字符集;使用 UTF-8 或更好的东西。
  2. 如果您的系统有业务需求需要我指定特定信息(例如邮政编码、县、州等),请单独要求。我所说的业务需求是指分析之类的东西;这些信息不应该与您当地的邮政服务共享(除非我也碰巧将相同的信息写入上面第 1 点的三行之一)。
  3. 有一个下拉列表,要求我指定我在上面第 1 点的行中提供的地址的分类位置,可能是国家。
  4. 如果您必须解析我在第 1 点中提供的信息,请使用我对第 3 点的回答来选择正则表达式。针对第 1 点中的信息运行该正则表达式以解析它。尝试使用正则表达式的输出填充第 2 点的用户界面元素。如果我更正了自动填充的信息,请使用我更改它的事实来改进您的正则表达式。同样,尽可能地给我一个机会来审查和纠正你的正则表达式的输出:没有人比我更清楚我想要传达的内容。

我发现,像这样构建的系统让我的生活变得更轻松。特别是当我将邮件发送到贵公司几乎没有功能性内部知识的邮政系统时。

如果您的公司确实有关于特定邮政系统的内部知识,请使用我在第 3 点中的选择来告知您向我显示的视图。很多人都知道美国邮政系统对包装的期望。如果我在第 3 点中选择美国,请随意使视图看起来适合美国地址。如果我选择一个你公司一无所知的国家——显示一个通用的三行,让我来做剩下的;不要强迫我使用 ASCII。

让我们在这里变得真实——建立一个包含所有全球邮政系统(公共和私人)的完整的百科全书式数据库充其量是一项艰巨的任务,如果不是不可能的话。例如,在邮政系统中,只有本地的最后一英里承运人才真正知道地址的位置。有时能够在包装上将便条传递给该承运人是非常有用的。将每个边缘案例载体的本地知识映射到您的数据库中确实是一项不可能完成的任务。

问问哥德尔。(然后问问自己,您是否正在尝试使用公理系统来模拟一个话语领域,给予或采用某种算术,如集合论或关系代数。)

于 2017-06-01T17:12:23.820 回答
7

地址

与@BenAlabaster 提供的出色答案截然相反,您可以简单地拥有:

address       TEXT(300)
postal_code   VARCHAR(15)
country_code  VARCHAR(2)

您的客户端表单布局仍然可以像您认为合适的那样复杂(或使用多行输入,用户可以手动输入他们的地址)。然后,您可以在必要时在地址中添加换行符。

国家

您的国家/地区表如下所示:

country_code  VARCHAR(2)
country_name  VARCHAR(255)

此外,您可以拥有以下之一

postal_code_required  TINYINT(1)
postal_code_regex     VARCHAR(255) NULL DEFAULT NULL

然后使用以下列表来设计您的国家/地区表:

于 2014-02-21T16:25:56.977 回答
2

Ben Alabaster 回答的评论:要根据国家/地区格式化地址,您可以使用一个格式化表,该表将每个国家/地区的列排序为单独的行。

  • AddressFormat(CountryCode, FieldName, FieldOrder)

也可以对字段顺序进行编码以使用复杂的网格布局。

按国家/地区分隔地址没有意义。随着国家数量的增加,这将变得混乱,如果你想找到一个国际客户的所有地址,你就会遇到麻烦。当您的地址同时包含建筑物编号和公寓编号时,使用 Ben 建议的地址类型也会导致歧义。我可能在一个公寓大楼里,每栋楼都有不同的名字。这在印度很常见。

于 2009-07-23T08:42:26.600 回答
2

我使用https://github.com/commerceguys/addressing库来格式化国际地址,他们使用这些元素:

Country
Administrative area
Locality (City)
Dependent Locality (in: BR, CN, IR, MY, MX, NZ, PH, KR, ZA, TH)
Postal code
Sorting code
Address line 1
Address line 2
Organization
Recipient

如果您想解析街道(名称、门牌号……),这无济于事。

顺便提一句。如果您正在寻找多语言国家/地区列表:https ://github.com/umpirsky/country-list

于 2016-08-22T15:53:03.880 回答
0

我知道这是一个已经回答的非常古老的话题,但我认为我也会投入两分钱。这完全取决于您的项目目标以及您希望目标用户如何输入地址。Ben 的建议将允许您准确地解析地址,但另一方面可能会使用户数据输入过程更长(并且可能更令人沮丧)。Stephen Wrighton 的建议更简单,因此用户输入地址可能更容易。

我还看到一些模型只有一个“地址”列,可以在一个列中捕获典型的街道号码、类型、街道名称、单元/公寓号码等,同时保留城市、国家、地区等。在其他列中。与 Stephen 的模型类似,除了 Address1、Address2 和 Address3 都合并为一列。

我的观点是,最灵活的模型往往是限制最少的模型,这取决于您对灵活的解释。

于 2010-09-08T13:31:09.907 回答
0

唯一的方法是将它们拆分为:

Name varchar,
Title varchar,
StreetAddress varchar,
StreetAddressLine2 varchar,
zipCode varchar,
City varchar,
Province varchar,
Country lookup

因为几乎每个国家/地区都有自己的地址数据标准,而且每个国家/地区都有不同格式的邮政编码。
您可以在我的帖子中从一个类似的问题中获得一小部分问题样本。

将每个国家/地区的地址分开应该没有意义,因为有些国家/地区的地址约定很少。一些流行的惯例包括在小村庄没有街道,只有村庄名称和编号,而街道位于大城市的地址。我了解到,在匈牙利首都布达佩斯,同名的街道很少(根据城市的区号区分),而其他城市则没有这样的地址(匈牙利的人可能会证实这是真的)。因此,地址格式的总数将是 numer_of_countries 乘以该国家/地区的地址格式数……可以用不同的表来完成,但这将是一项可怕的工作。

于 2009-07-21T15:05:12.747 回答