1

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

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

  • 旧金山
  • 圣弗兰
  • 顺丰

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

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

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

4

1 回答 1

0

对不起,我花了这么长时间才回来——我自私地在那里度假!如果您仍在为此工作:

好的,关于基础知识。假设您有一个名为“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”,它是一个运行时参数。

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

好的,所以您还想处理另一种情况:缩写,例如旧金山的“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 不能使用索引,因此这样的搜索意味着每次都进行全文件扫描。

如果您希望使用多种变体,我认为您需要一个昵称表。在这种情况下,我会创建一个不包含地点名称的“地点”表。然后创建一个 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 表中,而不仅仅是备用名称,这样您只需搜索一个表而不是两个表即可找到该地点。它简化了人类读者和数据库引擎的查询。

于 2013-07-24T16:41:44.400 回答