对不起,我花了很长时间才回来 - 我自私地去了那里度假!如果你仍然在这个工作:
好的,在基础知识。假设你有一个名为“place”的表和一个名为“city”的字段。你可以用“like”操作符在第一个多个字符上做一个简单的匹配。
select <whatever> from place where city like 'San Fran%';
您可能想要忽略大小写,所以“san fran”将匹配旧金山。在这种情况下:
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中,其中的参数有一个以“@”开头的名称。)
你会再上创建索引上(城市)和缩写(城市)保持快速。
如果你想要比这更灵活,那么我认为没有办法解决你想要处理的每一种情况。就像如果你希望用户能够输入“frisco”并找到旧金山或“拉斯维加斯”来获得拉斯维加斯,你可以在城市名称的任何地方搜索输入的字符串,即“城市像'%frisco%' ”。但是这有两个大问题。其一,我认为你会得到很多虚假的点击,可能其中很多对用户来说很神秘。就像输入“san”一样,不仅得到“旧金山”和“圣地亚哥”,而且还得到“加利福尼亚千橡树”。 (请参阅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)[email protected];
对于只有一个名称的地方,该地点只有一个place_name记录。
我说要将所有名称放在place_name表中,而不是只替换名称,以便您只需搜索一个表而不是两个找到该位置。它简化了人类阅读器和数据库引擎的查询。
请更具体地说明您希望如何连接数据。计算机是否应该知道“San Fran”和“San Francisco”是相同的地方,因为“Fran”是“Francisco”的前四个字母?它如何知道“SF”是“旧金山”而不是“San Fernando”或“Sfitzbergen”或“春田”?或者你打算在某处获得有效缩写列表? – Jay
感谢您回复杰伊!我想我所坚持的是实际将San Fran映射到旧金山的工具。你是对的,我可能会看@前几个字,但是有了缩写,我可能会用手去做普通的字。我比较小的细节更多地被卡在方法上。 – user2573743