从地理领域获得Max,Min for Lat和Long的替代方法?

时间:2014-02-10 22:02:24

标签: sql sql-server-2012 geospatial geography

我有不规则形状的地理区域。地理字段可以从定义该形状的数百到数千个纬度/长点变化。在尺寸方面,它可能来自几个美国。邮政编码达到整个美国的大小。为了提高性能,我在该字段上构建了Spacial索引。我经常需要找到基于特定区域内的纬度/长点的车辆。

我最初的做法就是这个。

WITH    LastP
          AS ( SELECT vlp.ID
                   ,GEOGRAPHY::STPointFromText('POINT(' + CAST(vlp.Long AS VARCHAR(20)) + ' '
                                               + CAST(vlp.Lat AS VARCHAR(20)) + ')', 4326) AS LastKnownPoint
                FROM LastPosition AS vlp )
    SELECT lp.ID
           ,zn.ZONE
        FROM dbo.GeogZone AS zn WITH ( NOLOCK )
        JOIN @zones AS z
            ON zn.Zone = z.Zone
        JOIN LastP AS lp
            ON lp.LastKnownPoint.STWithin(zn.ZoneGeog) = 1

我从表格LastPosition获取所有记录,而不是使用Geography函数将Lat / Long转换为JOIN点,然后转换为STWithin。这个过程很有效但速度很慢。我试图调整Spacial索引,但它没有发生重大变化。

为了提高性能,我想介绍以下过程。

从地理位置类型我将提取NorthLat, SouthLat, EastLong, WestLong 现在我可以在以下事项进行比较之前限制结果数量。

WITH    LastP
          AS ( SELECT vlp.ID
                   ,GEOGRAPHY::STPointFromText('POINT(' + CAST(vlp.Long AS VARCHAR(20)) + ' '
                                               + CAST(vlp.Lat AS VARCHAR(20)) + ')', 4326) AS LastKnownPoint
                FROM LastPosition AS vlp 
                WHERE (vlp.Long BETWEEN @WestLong and @EastLong) AND (vlp.Lat BETWEEN @SouthLat AND @NorthLat))
    SELECT lp.ID
           ,zn.ZONE
        FROM dbo.GeogZone AS zn 
        JOIN @zones AS z
            ON zn.Zone = z.Zone
        JOIN LastP AS lp
            ON lp.LastKnownPoint.STWithin(zn.ZoneGeog) = 1

以下是构建框的代码。

DECLARE @geomenvelope GEOMETRY;

DECLARE @BoundingBox AS TABLE
    (
     SouthLat DECIMAL(10, 8)
    ,NorthLat DECIMAL(10, 8)
    ,EastLong DECIMAL(10, 8)
    ,WestLong DECIMAL(10, 8)
    );

SELECT @geomenvelope = GEOMETRY::STGeomFromWKB(zn.ZoneGeog.STAsBinary(), zn.ZoneGeog.STSrid).STEnvelope()
    FROM dbo.GeogZone AS zn
    WHERE zn.Zone = 'CA-1'

INSERT INTO @BoundingBox (SouthLat,NorthLat,EastLong,WestLong)
        SELECT @geomenvelope.STPointN(1).STY 
               ,@geomenvelope.STPointN(3).STY 
               ,@geomenvelope.STPointN(1).STX 
               ,@geomenvelope.STPointN(3).STX 

SELECT *
    FROM @BoundingBox

我的问题:是否有另一种(更简单的)方法可以从我的地理领域获得东,西,北,南点?

1 个答案:

答案 0 :(得分:0)

很抱歉迟到的回复,但希望我能加点。

首先,转换为LastKnownPoint,您应该可以按如下方式声明:

GEOGRAPHY::Point(vlp.Lat, vlp.Long, 4326) AS LastKnownPoint

它的工作原理相同,但必须更容易阅读,不需要演员表。

为了获得更好的性能,如果您可以将Lat / Long存储为Geography列本身,则不必进行转换,如果您经常搜索会产生大量开销。这样做也可以让你直接使用Zone作为过滤器并使用空间索引,我不能高度推荐它。更不用说不再需要创建边界框了。

如果你不能做到这一切,至少减少CAST'ing和连接应该会在这里和那里获得相当长的几毫秒。