【发布时间】:2011-07-28 04:14:56
【问题描述】:
我使用来自http://geonames.org 的数据。表结构如下:
GN_Name 1 - 0:N GN_AlternateName
它们链接在:
(PK)GN_Name.GeoNameId == (FK)GN_AlternateName.GeoNameId
GN_Name 是包含所有地名的主表。 GN_AlternateName 包含其他语言的名称(如果有)。
前:
GN_Name.Name - Stockholm
GN_AlternateName.AlternateName - Estocolmo (if IsoLanguage=="es")
规则:
如果指定语言存在 GN_AlternateName.AlternateName 并且它以搜索字符串开头,我想使用它。
如果不是,我想使用 GN_Name.Name 如果它以搜索字符串开头。
我希望 GeoNameId 是唯一的。
基本上我只能在第一条记录中加入外部连接,但这似乎会降低性能。
我有以下 SQL(从 LINQ 查询基本修改的 SQL)。问题是,如果搜索字符串以“stock”开头,它只会找到“Estocolmo”。 "estoc" 什么也没产生。
select
distinct(n.GeoNameId) as Id,
an.IsoLanguage,
CASE WHEN (an.AlternateName like N'estoc%')
THEN an.AlternateName
ELSE n.Name
END AS [The name we are going to use]
from GN_Name as n
LEFT OUTER JOIN GN_AlternateName as an
ON n.GeoNameId = an.GeoNameId
AND 'es' = an.IsoLanguage
WHERE n.Name like N'estoc%'
更新
感谢 Rahul 和 Lee D。
我现在有以下内容:
select
distinct(n.GeoNameId) as Id,
an.IsoLanguage,
CASE WHEN (an.AlternateName like N'estoc%')
THEN an.AlternateName
ELSE n.Name
END AS [The final name]
from GN_Name as n
LEFT OUTER JOIN GN_AlternateName as an
ON n.GeoNameId = an.GeoNameId
AND 'es' = an.IsoLanguage
WHERE (n.Name LIKE N'estoc%' OR an.AlternateName LIKE N'estoc%')
这会对an.AlternateName 执行两次LIKE。有什么办法可以摆脱 LIKE 子句?
更新 2 Andriy M 使用 COALESCE 做了一个不错的替代查询。我稍微改了一下,结果如下:
SELECT Id, LocalisedName
FROM (
SELECT
n.GeoNameId AS Id,
an.IsoLanguage,
COALESCE(an.AlternateName, n.Name) AS LocalisedName
FROM n
LEFT JOIN GN_AlternateName AS an ON n.GeoNameId = an.GeoNameId
AND IsoLanguage = 'es'
) x
WHERE LocalisedName LIKE 'estoc%'
这个查询完全符合我的要求。谢谢!
【问题讨论】:
-
首先,您似乎错误地认为
DISTINCT仅适用于n.GeoNameId,而事实并非如此。DISTINCT适用于所有正在检索的列和表达式。 -
另外,如果您要搜索的本地化名称不存在怎么办?也就是说,结果实际上是可以预测的:你不会得到任何行。但这可以接受吗?
-
@Andriy M 你是对的。当本地化名称不存在时,我确实不需要标准名称。但是,我只想要每个位置的一条记录。有什么好的方法可以实现吗?
标签: sql-server-2008 case outer-join