1. 程式人生 > >SQL 查詢地理資訊中指定距離範圍內的記錄

SQL 查詢地理資訊中指定距離範圍內的記錄

目標:選取在指定位置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;
}