具有CTE和地理数据类型的额外子句

时间:2011-11-06 17:35:56

标签: sql sql-server geolocation sql-server-2008-r2 sqlgeography

我正在使用SQL Server中的Geography数据类型基于使用邮政编码的距离来创建一个匹配的查询。我有99%,但我有两个问题。目前,这通过zip,city和state搜索,但我还需要匹配[u.username]。我无法正确添加“OR Username LIKE @Name”的语法。其次,表现并不好。有来自美国各地的21名测试用户,查询需要4秒钟。

有没有办法加快速度并添加额外的搜索参数。到目前为止我有这个:

DECLARE @miles [float] = 10000;
DECLARE @myposition geography;
SELECT @myposition = GeoLocation FROM ZipCodes
WHERE Zip LIKE '11204';

SELECT z.*,z.GeoLocation.STDistance(@myposition) AS Distance INTO #HASHTABLE FROM ZipCodes z
WHERE z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
ORDER BY Distance asc

;WITH Results_CTE AS (SELECT u.*,z.GeoLocation.STDistance(@myposition) AS Distance, ROW_NUMBER() OVER (ORDER BY z.GeoLocation.STDistance(@myposition)) AS RowNum
FROM Users u INNER JOIN ZipCodes z ON u.PostCode = z.Zip
WHERE u.PostCode in (SELECT Zip from #hashtable) OR u.City in (SELECT City from #hashtable) 
) SELECT * FROM Results_CTE WHERE RowNum > 0 
DROP TABLE #Hashtable

2 个答案:

答案 0 :(得分:1)

你有声明的索引吗?我会放弃临时表并编写下面的查询,还要添加一些索引:在ZipCodes表(GeoLocation列上的空间索引)和用户表(在City和Zip列上)。

DECLARE @miles [float] = 10000;
DECLARE @myposition geography;
SELECT @myposition = GeoLocation FROM ZipCodes
WHERE Zip LIKE '11204';

SELECT u.*,z.GeoLocation.STDistance(@myposition) as Distance from Users u
INNER JOIN ZipCodes z ON u.PostCode = z.Zip
WHERE
    z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
AND
    u.Username LIKE '%'+@Name+'%'

UNION

SELECT u.*,z.GeoLocation.STDistance(@myposition) as Distance from Users u
INNER JOIN ZipCodes z ON u.City = z.City
WHERE
    z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
AND
    u.Username LIKE '%'+@Name+'%'

ORDER BY
    z.GeoLocation.STDistance(@myposition)

答案 1 :(得分:1)

谢谢@cipx,但我发现你的建议实际上已经重复了。在用新鲜的眼睛看着这个之后,我似乎有办法用AND或OR搜索多个字段。

DECLARE @miles [float] = 100;
DECLARE @myposition geography;
SELECT @myposition = GeoLocation FROM ZipCodes
WHERE Zip LIKE '28790'; --OR city like 'brooklyn';--'11204';

SELECT z.*,z.GeoLocation.STDistance(@myposition) AS Distance INTO #HASHTABLE FROM ZipCodes z
WHERE z.GeoLocation.STDistance(@myposition) <= (@miles*1609.344)
ORDER BY Distance asc

;WITH Results_CTE AS (SELECT u.*,z.GeoLocation.STDistance(@myposition) AS Distance, ROW_NUMBER() OVER (ORDER BY z.GeoLocation.STDistance(@myposition), userid) AS RowNum
FROM Users u INNER JOIN ZipCodes z ON u.PostCode = z.Zip
WHERE 
-- Using zip code and distance
-- u.PostCode in (SELECT Zip from #hashtable) 

-- using a link table to find users skilled in wrestling
-- OR UserID IN (SELECT UserID from UserSkills us INNER JOIN Skills s ON us.SkillID = s.SkillID WHERE s.Name LIKE 'wrestlin%') 

-- scalar properties of the UserProfiles table
-- DisplayName like 'johnny%'
) SELECT * FROM Results_CTE WHERE RowNum > 0 
DROP TABLE #Hashtable

这使我在大约一秒钟内在几个不同的字段上分页和查询超过300个用户,这不是很好但是现在可以接受。