首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Server地理

Server地理
EN

Stack Overflow用户
提问于 2016-08-02 11:04:31
回答 2查看 278关注 0票数 0

是否有可能改进以下查询:

代码语言:javascript
复制
DECLARE @radiusInMeters FLOAT = 400;
DECLARE @dgeog geography = geography::Point(given_latitude, given_longitude, 4326).STBuffer(@radiusInMeters);

select [fdx].latitude, [fdx].longitude
from [dbo].[fdx]
where @dgeog.STIntersects(geography::STGeomFromText('POINT(' + convert(varchar(20), [fdx].longitude) + ' ' + convert(varchar(20), [fdx].latitude) + ')', 4326)
                         ) = 1
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-02 14:05:28

kcung和Hasan BINBOGA是正确的,您需要一个空间索引。

查看您的查询:@dgeog.STIntersects( xxxx ) =1,这要求xxxx是地理数据类型。为了使xxxx成为地理数据类型,必须将STGeomFromText函数应用于行。因为这是WHERE子句的唯一部分,所以函数必须应用于所有行。

如果表fdx特别大,这意味着CLR函数必须一次又一次地应用。这不是一个快速的过程(用Server术语来说)。

试试看,如果可以的话:

代码语言:javascript
复制
ALTER dbo.fdx ADD Point AS (GEOGRAPHY::Point(Latitude, Longitude, 4326)) PERSISTED
GO
CREATE SPATIAL INDEX SIndex_FDX ON dbo.fdx (Point) 
USING GEOGRAPHY_GRID
WITH (
  GRIDS = (LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
  CELLS_PER_OBJECT = 1
)
GO
DECLARE @Latitude DECIMAL(15,10) = 0
DECLARE @Longitude DECIMAL(15,10) = 0
DECLARE @Radius FLOAT = 400
DECLARE @g GEOGRAPHY = GEOGRAPHY::Point(@Latitude, @Longitude, 4326).STBuffer(@Radius)
SELECT * FROM dbo.fdx WHERE Point.STIntersects(@g) = 1

注意:在使用lat/long对计算地理列之前,应该将它们转换为小数。当您使用浮点数作为输入时,有一个从浮点数到小数点到字符串的隐式转换,它会将坐标减少到小数点后的4位。如果您先显式转换,这将不是一个问题。

此外,如果dbo.fdx中有任何null lat/long值,则需要在WHERE子句中筛选它们,作为空值将导致空间索引不能正常工作。

票数 3
EN

Stack Overflow用户

发布于 2016-08-02 11:20:41

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38718689

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档