SQL 服务器地理位置
SQL Server Geography
是否有任何可能的方法来改进以下查询:
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
您可以创建空间索引:
https://msdn.microsoft.com/en-us/library/bb934196.aspx
kcung 和 Hasan BINBOGA 是正确的,您需要一个空间索引。
查看您的查询:
@dgeog.STIntersects(xxxx) = 1
这要求 [xxxx] 是地理数据类型。为了使 [xxxx] 成为地理数据类型,必须将 STGeomFromText 函数应用于该行。因为这是 WHERE 子句的唯一部分,所以该函数必须应用于 all 行。
如果tablefdx特别大,这意味着CLR函数将不得不反复应用。这不是(在 SQL-服务器术语中)一个快速过程。
试试这个,如果可以的话:
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 对转换为小数。当您使用浮点数作为输入时,会存在从浮点数到小数点再到字符串的隐式转换,这会将 trim 您的坐标降低到小数点后 4 位。如果您首先明确转换,那将不是问题。
此外,如果 dbo.fdx 中有任何 lat/long 空值,您需要在 WHERE 子句中过滤它们,因为空值将导致您的空间索引无法正常工作。
是否有任何可能的方法来改进以下查询:
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
您可以创建空间索引: https://msdn.microsoft.com/en-us/library/bb934196.aspx
kcung 和 Hasan BINBOGA 是正确的,您需要一个空间索引。
查看您的查询: @dgeog.STIntersects(xxxx) = 1 这要求 [xxxx] 是地理数据类型。为了使 [xxxx] 成为地理数据类型,必须将 STGeomFromText 函数应用于该行。因为这是 WHERE 子句的唯一部分,所以该函数必须应用于 all 行。
如果tablefdx特别大,这意味着CLR函数将不得不反复应用。这不是(在 SQL-服务器术语中)一个快速过程。
试试这个,如果可以的话:
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 对转换为小数。当您使用浮点数作为输入时,会存在从浮点数到小数点再到字符串的隐式转换,这会将 trim 您的坐标降低到小数点后 4 位。如果您首先明确转换,那将不是问题。
此外,如果 dbo.fdx 中有任何 lat/long 空值,您需要在 WHERE 子句中过滤它们,因为空值将导致您的空间索引无法正常工作。