我们有一个团队为软件开发人员设计表格和关系。在我们的组织中,他们对执行3NF标准化非常严格-坦白地说,鉴于我们的组织规模以及需求或客户随时间的变化,我同意。我对他们的设计决定背后的原因只有一个不清楚的地方:地址。 。地址的每个部分在地址表中都有自己的列。例如,以这个粗糙的美国地址为例:

Attn: Jane Doe
485 1/2 N Smith St SW, APT 300B
Chicago, IL 11111-2222


它会像这样在数据库中分解:


街道编号:485
街道分数:1/2
街道前向:N(北)
街道名称:Smith
街道类型:ST(街道)
街道邮政方向:西南(西南)
城市:芝加哥
州:伊利诺伊州伊利诺伊州
邮编:11111
邮编4:2222
国家(假定为美国)
注意:Jane Doe
PO方框:NULL
住所类型:APT(公寓)
住所号:300B

还有其他一些与乡村路线和合同路线有关的栏目。此外,我们的特定应用程序可能会包含一些国际地址。数据建模人员说,他们将添加特定于国际地址的列,这些列将是常规的第1行,第2行字段。反复进行在线搜索是指使用地址行1、2、3和可能的4,然后划分城市,地区和邮政编码。我们的新应用程序确实有一个用例,其中这种粒度是有益的。我们必须验证用户没有创建重复业务,并且检查地址是验证之一。我们可以使其与地址线1和2一起使用,但这会更加困难。

对于我们的特定应用程序,我们需要为企业和个人存储多种地址(物理地址,邮件地址,运输地址等)。我们可能需要生成可打印的套用信函,但到目前为止尚未讨论该要求。

我们组织中的其他一些应用程序需要支持:


审核(具有完整的历史记录表)
打印邮件标签
生成打印的表格
报告(适用于国家和地区政府)

虽然我们的应用程序可能无法完成所有工作其他应用程序正在执行的工作,将地址拆分为多个组件是我工作的企业标准。不论我们的应用程序是否将从中受益,我们都被迫这样做。 br />
为了让我更好地理解他们的设计决策,并向我们的客户推销自己的想法...

通过将街道地址分成多个单独的列可以解决哪些问题?

因实施此类系统而遇到问题的任何人都将获得奖励积分。

评论

并且请记住,有些地址仍然不适合您的模板-我看到了一些发展中国家沿“从水泥厂到街上”的真实街道地址。

@duskwuff:我向他们提出了这个,这就是为什么他们添加“国际地址字段”-line_1,line_2,line_3。他们真的只是想拆分美国地址。公平地说,这些应用程序中> 90%的地址是美国地址。但是我完全理解你来自哪里。

强制链接:mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses

#1 楼

拆分可以解决的问题包括

验证可以将名称的任何一部分与主列表进行比较。那些不匹配的可以被拒绝。邮政编码是一个明显的例子。这些由独立机构发布和维护。唯一有效的邮件是由该机构签发的邮件。拥有相应的列会产生切实的业务价值。

分析以地理分层的方式了解订单的去向很有用。这可能会推动销售计划,产品开发或佣金支付等。

代码重复通过使组织中的所有应用程序都采用相同的数据模型(最复杂的消费者的数据模型),可以将单个代码库在整个企业范围内采用并保持一致。可以避免无休止地重复头发分裂,或者至少将其分配给螺旋桨头。由组织的不同部分持有的地址可以一致地更新。可以提高客户服务和满意度。开发工作可以集中于系统的独特,高价值的部分。

法律问题法律和税收因管辖权而异。通过分别捕获详细的地址值,可以更容易地将事务数据与合规性要求进行交叉引用。 。完全解析的地址更易于比较。这可能是一个简单的数据质量问题,或者,例如,如果多个空壳公司向同一交货地址下达大笔订单,或者使用信用卡在短时间内向许多分散的位置交货,则可能会产生合规性或信誉问题。 br />
单独存放的格式化部件可以按照适合当前需求的任何方式组合。如果说长而薄的打印标签变得便宜,则可以重新格式化以使用它们。这种类型的数据在收集时比在后期分析中要容易得多,在源头进行解析和验证。因此,即使是YAGNI,也可以花很少的成本预先投入额外的精力,并可能节省大量的未来。

最后,我不会忽略人为因素。数据模型由数据建模人员生成。这就是他们所做的。那是他们的职业。他们不会告诉您只是将其转储到BLOB中,对吗?

评论


我认为这是一个被低估的答案。大多数答案都解决了将地址分成几列可能引起的许多问题,但我认为此答案最能总结出解决的问题。我可能会发布类似的问题,询问所引入的问题。每个解决方案都有其优点和缺点。您的回答将最大程度地解决您的问题。

– Greg Burghardt
16 Mar 30 '16 at 12:26

#2 楼

我花了7年的时间为一家出版公司开发软件,而我们所解决的最棘手的问题之一就是解析订阅列表中的街道地址。将地址划分为不同的字段很有用,但是您永远不能为人脑可以设计的地址格式和组件的每一种可能的病理畸变进行设计。

每个地方都有其怪癖,而这只是在美国。扔到其他国家/地区,对于想解析每个地址的任何方法,事情很快就会变得难以处理。仅是两个示例:

在西班牙,街道编号始终位于街道名称和逗号之后,并且许多地址包含序号(例如1°或3ª)的地板编号,以及“ left”的缩写”(“ Izda”是指您上楼梯后的左门),“ right”(“ Dcha”)或其他可能性。现在,将这些古怪性乘以具有不同历史习俗的地址的不同国家和地区的数量...(日本?英格兰乡村?韩国?中国?)

在俄勒冈州波特兰市,有NS和EW将城市划分为NW,NE,SW和SE象限的轴(以及N“象限”,但我离题)。 NS街道从该轴开始以东西方向递增编号,而EW街道上的地址则由NS街道编号决定,即该数字的“百个街区”(即,在EW街道上第11和第12大街之间的房屋会有一个数字像1123)。美国地址的相当标准的东西。

您经常碰到波特兰地址,例如0205 SW NebraskaSt。前导零吗? WTF?我的integer列中有房屋“编号”。

建立网格后,N-S轴由Willamette河定义。河流以东的一切都是东北或东南,河流以西或西北。随着城市向南发展,他们遇到了一条不便的事实,即河流向东蜿蜒,因此将轴线向南投影时,您会遇到这个有问题的区域,该区域位于河流的“西侧”,但位于轴线的东侧。解决方案是添加一个前导零,实际上是一个负号,数字从轴线向东递增。

如果您是我,我会放弃设计最终系统的希望。您无法涵盖所有​​可能性,而随着人类进入未开发的土地,将会创造出新的可能性。

对于美国地址,请看一下USPS在地址标准化中所做的事情,并记住将house_number列设为varchar。在查看时,您将弄清楚如何解析1634 EN Fort LaneAve。

对于世界其他地区,我可能会尝试抽象出其他字段以覆盖80-90可能出现的百分比,并提供一组未解释的字段,可以在必要时处理其他所有内容。即如果您的解析器无法处理地址,则将其保存为未解析并进行标记。如果您确实要解析地址,请确保记住了找到各个字段的顺序,以便可以将其重新组合成可交付的内容。

我要说的是,最重要的字段是将会是邮政编码,但即使在很多地方也无法做到。

祝你好运。这可能是一个有趣且令人沮丧的工作,但保持头脑清醒的关键是知道何时退出尝试,仅存储未解析的输入,或将与原始输入部分解析的输入作为备份。

评论


街道编号中前导零的有趣跟进:HTML数字INPUT元素会将前导零发回服务器:。我担心它不会(至少在Firefox中会这样)。

– Greg Burghardt
16 Mar 29 '16 at 15:59

那么,为什么拆分有用呢?只为地址提供3个字符串“行”怎么办?

–usr
16-3-29在19:57

还有从IN到WI常见的137 SE Chestnut Ave SW模式。

–罗斯压机
16-3-29在23:19



@usr并非每个地址都适合三行-仅使用varchar和自由格式的多行文本字段即可!

–user253751
16-3-30在3:17



我仅举两个例子,但还有很多。伦敦西北1区,波特曼广场,埃塞克斯大厦22号。 “ 22”是公寓号码。

–吉姆·加里森(Jim Garrison)
16 Mar 30 '16 at 4:19

#3 楼

像所有设计问题一样,有一个非常严格的“取决于”。这取决于您的数据故事-如何收集数据,如何使用数据,如何更新数据等。我的所有评论都应作为讨论点,而不是方法回答。

它听起来*,您可以通过使用地址验证服务来获得更多收益,而不是尝试自己构建一个。虽然这些服务价格昂贵,但许多此类服务都提供了很大的邮寄折扣。

当然,对于某些数据故事,这里有一个折衷之处。您可以保留解析出的地址片段,并为组合的地址创建一个计算列(可能是一组列)。这是一个实现答案,暗示了所有正常的警告。

我已经实现了解析的地址设计。对于数据质量和数据处理需求,我们绝对需要这样做。但这是一家具有物理地址,邮政地址,虚拟地址等的公司。

另一个可能出现的问题是,不同的邮政服务要求以不同的格式/顺序显示相同的信息/等等。因此,对零件进行建模可以支持以各种格式和布局显示相同的信息。

最后,您不需要国际业务就可以支持国际数据。甚至美国公司也需要支持国际地址。假设您永远都不会拥有它,这是一个巨大的数据错误。客户搬家,供应商更改总部,即使他们有美国总部,供应商联系信息也可以是国际性的。即使您当前的系统犯了这个错误,您也不想继续前进。

我强烈推荐Graham Rhind撰写的著作和博客。他是有关各种地址及其相关权衡的数据领域的专家。


*我在这里所说的只是一个概括。对于设计解决方案,我有很多问题需要帮助,可能需要花费几个小时的时间。也可能有一些图片和一些数据分析。然后是关于地址的许多非常古怪的数据故事。

评论


“您不需要国际业务就可以支持国际数据。”-非常正确。最重要的是,我们实际上位于另一个国家的边界​​附近。建模团队确实提供了国际地址的解决方案,即在数据库中提供第1行,第2行和第3行字段。

– Greg Burghardt
16 Mar 28 '16 at 18:56

尽管您说“这是一个概括”,但对于我们拥有企业范围的地址而言,“一刀切”的解决方案使您的答案更加适用。

– Greg Burghardt
16 Mar 28 '16 at 18:57

#4 楼

完全撇开正确地解析人们提供的不可预测的乱码的巨大挑战,解析的好处是它为您提供了用于分组和排序的维度。例如,邮政编码。但是,解析一个特定的维度并没有收益,直到您需要对该维度进行分组或排序为止。

反正什么是地址?您可以很好地说明它是一个位置标识符,但在情况上也可以很好地说明它是交货说明-“从水泥厂下街”。在澳大利亚,人们认为邮政编码是位置标识符,但不是,它们是路由代码-交货说明。 4702是Rockhampton Mail Centre,这是一个主要的分发节点,服务于从海域延伸到内陆300 km的采矿小镇Emerald的区域。将字符串转换成GPS坐标,然后将其与未解析的字符串一起存储在一个小的简单表格中。他们使用唯一的通用方法,始终有可能获得持续良好的结果:排名加权的部分匹配项与经过验证的结果的巨大数据库。

如果您想要交付说明,仍然建议您保留未分析的字符串因为它可能包含任何东西。

请注意,在两种情况下,我都建议保留未分析的字符串。这是因为


它本身就是有用的
有一天,您将想出如何解析它的方法
几天后,您将想出如何正确解析

这永远不会结束

可以说地址始终是传递指令,至少包含一个位置标识符。一封写给“ 123 Main st,Emerald 4702”的信编码了三个位置:Rockhampton北部的RMC,Emerald和街道地址。罗克汉普顿邮局只会将其发送给RMC。 RMC将其发送到Emerald邮局,Emerald邮局希望知道在哪里可以找到Main Main123。

评论


“无论如何,这是什么地址?...您也可以提出一个很好的案例,即它的交货说明”-非常好。我认为在这种情况下,地址的“位置”方面和“交付说明”方面应该是数据库中的单独字段。

– Greg Burghardt
16-3-29在13:24

#5 楼

分隔邮政编码/邮政编码,建筑物名称,道路名称可能很有意义。但是,当您开始添加“城镇”,“区域”等时,就变得比第1行,第2行等更具疑问。问题是,即使我和我的妻子也无法同意我们所居住的城镇的名称!是将“村庄”名称放置在城镇区域中,还是放在道路名称下方的行中,而将本地城市放置在城镇区域中? (如果您称他们居住的是村庄而不是城镇,就会有人得罪,而如果您称城镇而不是村庄的话,居住在同一地点的其他人将会得罪!)做任何事情都不比您使用的地址验证系统好。但是情况变得更糟。在英国,所有地址都应该有邮政编码,但是直到房屋盖好后的某个时间才分配邮政编码……因此,系统必须允许打破关于地址的所有规则!

评论


Amazon.uk是我所见过的最好的系统,当我输入地址时,他们会给我选择使用最匹配的“认可”地址的选项。但是,批准的地址通常是建筑物中的其他公司的地址,或者不包含“楼层”等信息,因为邮局只在乎信箱是什么,而不在乎拿什么进行签名。

–伊恩·林格罗斯(Ian Ringrose)
16-3-29在12:59

#6 楼

我曾经在荷兰实施过这样的系统。事实是,这类信息可能以比您想象的更多的方式变化。重命名街道,合并城市,更新邮政编码等。能够在不将地址解析为单个字符串的情况下更新此类信息真是太好了。

#7 楼

除了在其他答案中已经提到的问题外,在某些语言中(尤其是日耳曼语),街道名称也很复杂。例如,在许多德国城镇中,通常都有一条“ Bahnhofstrasse”,即通往火车站的街道(“ Bahnhof”是指铁路/火车站,“ Strasse”是指街道)。当然,您可以将这两个部分分离开来,但是现在,如果要(以编程方式)将它们放回一起,就会遇到变形问题。您经常使用“ Rue de la Pais”或“ Boulevard desChamps-Élysées”的街道名称。现在,您有了一个介词(“ de”)和一个定冠词(“ le”或“ la”),它们可以组合在一起。它们代表街道类型或街道名称的一部分吗? (您可能需要将它们存储在某个地方,否则您将再次陷入变形。)


我曾经建模过类似的东西。但这对于中型大学(在美国)的住宅物业维护办公室来说是一个很小的应用程序。由于以下原因,我对地址进行了非常细化:


该地区有一些街道具有相同的名称,但街道的“类型”不同(例如,“伍兹大街”与“伍兹法院” “)。
用户希望能够优化维护工作,例如如果同一块上有两个或多个服务请求,这些请求可以同时处理。
用户希望能够关联同一建筑物中不同单元(公寓)之间的问题-例如如果有多个公寓报告温度过低或热水不足。

...以及我不再记得的其他原因。 (这是在1980年代后期。)

再说一次,这只是有道理的,因为要处理的地址(和地址格式化规则)数量很少。我不相信这种方法可以扩展,即使限于美国地址,由于其他答案中已经给出的原因。

评论


您的1980年代示例很好地说明了我的观点,即解析出您需要操纵的任何尺寸,而“ ...存储它们或您将要变形”是一个很好的例子,说明为什么保留源文本至关重要。它不可避免地包含各种必须保留的非功能性内容。说到无关紧要但有趣的事情,林荫大道的意思是“建在拆除的防御城墙之上的长廊”。

– Peter Wone
16-3-30在23:53