Oracle spatial search within distance

后端 未结 4 1348
予麋鹿
予麋鹿 2021-02-03 15:59

I have the following table Cities:

ID(int),City(char),latitude(float),longitude(float).

Now based on a user`s longitude(ex:44.8) and latitude(e

4条回答
  •  时光取名叫无心
    2021-02-03 16:25

    If you decide to make your own formula, I think this function could be very useful for oracle users and could be modified slightly for other DB's. This is the flat earth formula which is a lot less computationally expensive than the more accurate haversine formula.

    CREATE OR REPLACE Function CIC3.F_FLATEARTHRAD
       ( latoriginrad IN number,
         longoriginrad IN number,
         latdestrad IN number,
         longdestrad IN number)
    
    RETURN  number IS
       a number;
       b number;
       c number;
       u number;
       v number;
    
       HalfPi number:=1.5707963;
       R number:=3956;
    BEGIN
       if latoriginrad is null or latdestrad is null or 
       longdestrad  is null or  longoriginrad is null then
             return null;
       end if; 
       a := HalfPi - latoriginrad;
       b := HalfPi - latdestrad;
       u := a * a + b * b;
       v := - 2 * a * b * cos(longdestrad - longoriginrad);
       c := sqrt(abs(u + v));
    
       return R * c;
    END;
    

    Then your query becomes

    select * from GEO.Cities a
    where F_FLATEARTHRAD(44.8*0.0174,46.3*0.0174,
                   latitude_radians,longitude_radians)<1000 
    

    The 0.0174 factor is needed because the formula uses radians not degrees. So you would need to either store radians (maybe with a trigger). Or you would need to modify the formula to accept degrees. For query purposes you may be querying thousands of records and even a single extra multiplication can make a difference in response time. In our case some queries compare distances between two tables 4k records on one and 200k so we have in the order of billions of function calls.

    Below is the haversine equivalent for people not needing to worry about time.

    CREATE OR REPLACE Function CIC3.F_HAVERSINE 
      ( latorigin IN number,
        longorigin IN number,
        latdest IN number,
        longdest IN number)
    
      RETURN  number IS
        v_longoriginrad number;
        v_latoriginrad number;
        v_longdestrad number;
        v_latdestrad number;
        v_difflat number;
        v_difflong number;
        a number;
        c number;
        d number;
        z number;
        x number;
        e number;
        f number;
        g number;
        h number;
        i number;
        j number;
        k number;
        l number;
        m number;
        n number;
        o number;
        p number;
        q number;
        y number;
    BEGIN
        z := .017453293;
        x := 3956;
        y := 57.295780;
        v_longoriginrad:=longorigin*z;
        v_latoriginrad:=latorigin*z;
        v_longdestrad:=longdest*z;
        v_latdestrad:=latdest*z;
        v_difflong:=v_longdestrad-v_longoriginrad;
        v_difflat:=v_latdestrad-v_latoriginrad;
    
        j:=(v_difflat/2);
        k:=sin(j);
        l:=power(k,2);
    
        m:=cos(v_latoriginrad);
    
        n:=cos(v_latdestrad);
    
        o:=v_difflong/2;
        p:=sin(o);
        q:=power(p,2);
    
        a:=l+m*n*q;
    
        c := 2 * asin(sqrt(a));
    
        d := x * c;
    
        return d;
    END; 
    

提交回复
热议问题