SQL 查詢地理資訊中指定距離範圍內的記錄
阿新 • • 發佈:2019-01-03
目標:選取在指定位置1公里範圍的記錄
測試資料:指定時間範圍內,16萬記錄
跟據測試結果,如果不是需要很高精度,用第一種方法就可以了
方法1:按矩形算
優點:快,缺點:不是圓型的範圍,平均執行150ms
DECLARE @GGP_LOCATE_POINT GEOGRAPHY = GEOGRAPHY::Point( 22.26663,113.821256666667, 4326);
DECLARE @FLT_LONGITUDE FLOAT, @FLT_LATITUDE FLOAT --緯度
SELECT @FLT_LONGITUDE =113.821256666667, @FLT_LATITUDE =22.26663
SELECT @GGP_LOCATE_POINT.STDistance(GEOGRAPHY::Point([LATITUDE],[LONGITUDE], 4326)) as [驗證距離], * FROM [目標表]
WHERE [ALERT_TIME] BETWEEN '2015-09-08' AND '2015-09-28'
AND [LATITUDE] BETWEEN @FLT_LATITUDE-0.010 AND @FLT_LATITUDE+0.010
AND [LONGITUDE] BETWEEN @FLT_LONGITUDE-0.010 AND @FLT_LONGITUDE+0.010
方法2:計算每個座標的距離(圓),平均執行5500ms
DECLARE @GGP_LOCATE_POINT GEOGRAPHY = GEOGRAPHY::Point( 22.26663,113.821256666667, 4326);
SELECT * FROM [dbo].[ALERT]
WHERE [ALERT_TIME] BETWEEN '2015-09-08' AND '2015-09-28'
AND @GGP_LOCATE_POINT.STDistance(GEOGRAPHY::Point([LATITUDE],[LONGITUDE], 4326))<=1000
方法3:計算目標是否在範圍內,平均執行7500ms
DECLARE @GGP_LOCATE_POINT GEOGRAPHY = GEOGRAPHY::Point( 22.26663,113.821256666667, 4326);
DECLARE @buffer GEOGRAPHY;
set @[email protected]_LOCATE_POINT.STBuffer(1000);
SELECT * FROM [dbo].[ALERT]
WHERE [ALERT_TIME] BETWEEN '2015-09-08' AND '2015-09-28'
AND @buffer.Filter(GEOGRAPHY::Point([LATITUDE],[LONGITUDE], 4326))>1000
補充:計算指定範圍對應的經緯度大小
//地球子午線(南極到北極的連線)長度39940.67公里,緯度一度合110.94公里,一分合1.849公里,一秒合30.8米,不同緯度的間距是一樣的。
//地球赤道圈長度40075.36公里,深圳在北緯22度左右,緯度圈長為111.32*cos(a),
//因此這裡的經度一度合103.566436555110152670083196192
/// <summary>
/// 獲取指定距離的經度
/// </summary>
/// <param name="org">對應的緯度</param>
/// <param name="range"></param>
/// <returns></returns>
public double GetLongitude(double org, float range)
{
// 1 經度的距離為 111.32*cos(a)
const double n = 1113200f;
double angle = Math.PI * org / 180.0;
return range / (n * Math.Cos(angle));
}
/// <summary>
/// 獲取指定距離的緯度
/// </summary>
/// <param name="org"></param>
/// <param name="range"></param>
/// <returns></returns>
public double GetLatitude( float range)
{
// 1 緯度的距離為 110.94公里
const double n = 1109400f;
return range / n;
}