【问题标题】:Extra clauses with a CTE and Geopgraphy datatype具有 CTE 和 Geography 数据类型的额外子句
【发布时间】:2011-11-06 17:35:56
【问题描述】:

我正在使用 SQL Server 中的 Geography 数据类型创建一个查询,以根据人们使用邮政编码的距离进行匹配。我在那里有 99%,但我有两个问题。目前,此搜索按 zip、城市和州进行,但我还需要在 [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

【问题讨论】:

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


    【解决方案1】:

    您是否声明了任何索引?我将放弃临时表并编写以下查询,还添加一些索引:ZipCodes 表(GeoLocation 列上的空间索引)和 users 表(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)
    

    【讨论】:

    • 是的,我有关于城市、州、zip、lat、long 和 lat/lng 的索引。不过我会试一试。谢谢。
    【解决方案2】:

    感谢@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 多个用户进行分页和查询,这不是很好,但现在可以接受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 2019-03-03
      • 2018-05-27
      相关资源
      最近更新 更多