【问题标题】:How do I normalize dataset A to dataset B?如何将数据集 A 标准化为数据集 B?
【发布时间】:2013-07-11 17:47:24
【问题描述】:

我有两个位置数据集;一个是创建的数据集,其中包含世界上每个城市的列表,另一个是来自用户输入的位置数据。

我想将所有用户输入数据映射到完整的数据集。例如,用户输入的数据可能有多行:

  • 旧金山
  • 旧金山
  • 顺丰

我想将所有这些行映射到完整数据集中的旧金山。

您会推荐哪些程序、方法、工具等?我想过正则表达式,但我不知道如何自动化它以搜索所有不同的城市。

澄清:计算机不知道像 SF 这样的东西是否应该代表旧金山,这取决于人类的判断。一般来说,我正在寻求有关如何解决此问题的帮助。我不知道如何将一组映射到另一组,这就是我坚持的部分

【问题讨论】:

  • 请更具体地说明您希望如何连接数据。计算机是否应该知道“San Fran”和“San Francisco”是同一个地方,因为“Fran”是“Francisco”的前四个字母?它怎么会知道“SF”是“San Francisco”而不是“San Fernando”或“Sfitzbergen”或“Spring Field”?或者您是否打算在某处获取有效缩写列表?
  • 感谢杰伊的回复!我想我坚持的是实际将旧金山映射到旧金山的工具。你说得对,我可能会看@前几个字符,但是对于缩写,我可能会手动做常见的。比起小细节,我更倾向于方法。

标签: dictionary location dataset mapping normalization


【解决方案1】:

对不起,我花了这么长时间才回来——我自私地去那里度假了!如果你还在做这个:

好的,基本的。假设您有一个名为“place”的表和一个名为“city”的字段。您可以使用“like”操作符对前几个字符进行简单匹配。

select <whatever> from place where city like 'San Fran%';

您可能希望忽略大小写,因此“san fran”将匹配 San Francisco。在这种情况下:

select <whatever> from place where upper(city) like upper('San Fran%');

当然在现实生活中你不会硬编码“San Fran”,它会是一个运行时参数。

在城市上创建一个索引,这会非常快。如果使用“upper”使其不区分大小写,则在 upper(city) 上创建索引。

好的,所以您还想处理另一种情况:缩写,例如旧金山的“SF”。

你没有说你正在使用什么风格的 SQL。如果它支持函数,您可以编写一个函数,该函数将形成任何名称的缩写。该函数可以使用子字符串(或您的 SQL 具有的任何等效项——我认为这些函数不是很标准)扫描名称的字符,查找空格,然后拉出第一个字符,然后是空格后面的每个字符,然后返回。假设您将此函数称为“abbreviate()”。那么查询将是:

select <whatever> from place where upper(city) like concat(@city,'%') or abbreviate(city) = @city;

(上面是在 MS SQL Server 中的样子,其中参数的名称以“@”开头。)

然后您将在 upper(city) 和 abbreviate(city) 上创建索引以保持快速。

如果您想比这更灵活,那么,我认为没有任何办法可以考虑您要处理的每个案例。就像如果您希望用户能够输入“frisco”并找到 San Francisco,或“vegas”获得 Las Vegas,您可以在城市名称中的任何位置搜索输入的字符串,即“city like '%frisco%' ”。但这有两个大问题。一,我认为你会得到很多错误的点击,其中很多可能对用户来说相当神秘。像输入“san”,得到的不仅仅是“San Francisco”和“San Diego”,还有“Thousand Oaks, California”。 (看到 thouSANd 中的“san”了吗?)第二,当 LIKE 子句以通配符开头时,SQL 不能使用索引,因此像这样的搜索意味着每次都进行全文件扫描。如果您希望在用户输入“Beantown”时找到波士顿或在用户输入“大苹果”时找到纽约,那么您就处于完全不同的领域了。

如果您希望使用范围广泛的变体,我认为您需要一个昵称表。在这种情况下,我会创建一个不包含地点名称的“地点”表。然后创建一个 place_name 表,其中包含您要接受的名称的所有变体。在 place_name 和 place 之间创建多对一关系。在 place_name 中包含一个字段,用于标识哪个是“主名称”。那么查询就变成了:

select n2.name, p.place_id, <whatever>
from place_name n 
join place p on n.place_id=p.place_id
join place_name n2 on n2.place_id=n.place_id and n2.is_primary=1
where n.name like concat(@name,'%') or abbrev(n.name)=@name;

对于只有一个名称的地点,该地点只有一个 place_name 记录。

我说将所有名称放在 place_name 表中,而不仅仅是备用名称,这样您只需搜索一个表而不是两个表即可找到该地点。它简化了人类读者和数据库引擎的查询。

【讨论】:

    猜你喜欢
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2019-05-01
    • 2020-08-26
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多