복붙노트

[SQL] SQL 쿼리와 가까운 위도 / 경도 찾기

SQL

SQL 쿼리와 가까운 위도 / 경도 찾기

내가 위도와 경도가 있고 내가 그 거리가 지정된 하나보다 더 얻는 경우에, 거리가 가까운 위도와 경도를 가지고있는 데이터베이스에서 레코드를 끌어하고자, 다음을 검색하지 않습니다.

테이블 구조 :

id
latitude
longitude
place name
city
country
state
zip
sealevel

해결법

  1. ==============================

    1.

    SELECT latitude, longitude, SQRT(
        POW(69.1 * (latitude - [startlat]), 2) +
        POW(69.1 * ([startlng] - longitude) * COS(latitude / 57.3), 2)) AS distance
    FROM TableName HAVING distance < 25 ORDER BY distance;
    

    여기서 [starlat] 및 [startlng은 상기 거리를 측정하기 시작하는 위치이다.

  2. ==============================

    2.당신은 MySQL의 테이블을 만들 때, 위도 및 경도 속성에 특히주의해야합니다. Google지도의 현재 줌 기능을 통해, 당신은 단지 소수점 뒤 6 자리의 정밀도를 필요로한다. 최소한 테이블에 필요한 저장 공간을 유지하기 위해, 위도 및 경도 속성의 부동 소수점 크기를 (10,6) 지정할 수 있습니다. 즉, 필드는 소수점 이후 6 자리를 저장, 플러스 4 자리까지 소수점 전에, 예를 들어 드릴 것입니다 -123.456789도. 표에는 기본 키 역할을하는 id 속성이 있어야합니다.

    당신은 MySQL의 테이블을 만들 때, 위도 및 경도 속성에 특히주의해야합니다. Google지도의 현재 줌 기능을 통해, 당신은 단지 소수점 뒤 6 자리의 정밀도를 필요로한다. 최소한 테이블에 필요한 저장 공간을 유지하기 위해, 위도 및 경도 속성의 부동 소수점 크기를 (10,6) 지정할 수 있습니다. 즉, 필드는 소수점 이후 6 자리를 저장, 플러스 4 자리까지 소수점 전에, 예를 들어 드릴 것입니다 -123.456789도. 표에는 기본 키 역할을하는 id 속성이 있어야합니다.

    CREATE TABLE `markers` (
      `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
      `name` VARCHAR( 60 ) NOT NULL ,
      `address` VARCHAR( 80 ) NOT NULL ,
      `lat` FLOAT( 10, 6 ) NOT NULL ,
      `lng` FLOAT( 10, 6 ) NOT NULL
    ) ENGINE = MYISAM ;
    

    테이블을 생성 한 후, 그것의 시간을 데이터로 채 웁니다. 아래에 제공된 샘플 데이터는 미국 전역에 흩어져있는 180에 대한 피자 가게입니다. phpMyAdmin에, 당신은 CSV (쉼표로 구분 된 값) 등 다양한 파일 형식을 가져 오기 탭을 사용할 수 있습니다. Microsoft Excel 및 Google 스프레드 시트 CSV 형식으로 모두 수출, 당신은 쉽게 / 내보내기 CSV 파일 가져 오기를 통해 MySQL의 테이블 스프레드 시트에서 데이터를 전송할 수 있습니다.

    INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Frankie Johnnie & Luigo Too','939 W El Camino Real, Mountain View, CA','37.386339','-122.085823');
    INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Amici\'s East Coast Pizzeria','790 Castro St, Mountain View, CA','37.38714','-122.083235');
    INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Kapp\'s Pizza Bar & Grill','191 Castro St, Mountain View, CA','37.393885','-122.078916');
    INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Round Table Pizza: Mountain View','570 N Shoreline Blvd, Mountain View, CA','37.402653','-122.079354');
    INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Tony & Alba\'s Pizza & Pasta','619 Escuela Ave, Mountain View, CA','37.394011','-122.095528');
    INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Oregano\'s Wood-Fired Pizza','4546 El Camino Real, Los Altos, CA','37.401724','-122.114646');
    

    주어진 위도 / 경도의 특정 반경 거리 내에있는 마커 테이블의 위치를 ​​찾으려면 Haversine 수식을 기반으로 SELECT 문을 사용할 수 있습니다. 하버 사인 수식 구형 좌표 두 쌍의 사이에 큰 서클 거리를 계산하기 위해 일반적으로 사용된다. 이 프로그램에 관련된 심층 수학적인 설명은 무버블 타입의 사이트에 위키 백과와 식의 좋은 토론에 의해 주어진다.

    여기에 37 반경 25 마일 이내에있는 가장 가까운 (20 개)의 위치를 ​​찾을 수 SQL 문이있어, -122 좌표입니다. 이는 해당 행의 위도 / 경도 및 목표 위도 / 경도에 기초하여 거리를 계산하고, 거리 값이 25 미만이고 행만 요청 주문을 전체 쿼리 거리, 및 20의 결과에 기준하여. 대신 마일 킬로미터 검색 6371과 3959을 대체합니다.

    SELECT 
    id, 
    (
       3959 *
       acos(cos(radians(37)) * 
       cos(radians(lat)) * 
       cos(radians(lng) - 
       radians(-122)) + 
       sin(radians(37)) * 
       sin(radians(lat )))
    ) AS distance 
    FROM markers 
    HAVING distance < 28 
    ORDER BY distance LIMIT 0, 20;
    

    이 사람은 거리에 적은 이십팔마일보다 위도와 경도를 찾는 것입니다.

    또 다른 하나는 28 이십구마일 사이의 거리에서 그들을 찾을 수 있습니다 :

    SELECT 
    id, 
    (
       3959 *
       acos(cos(radians(37)) * 
       cos(radians(lat)) * 
       cos(radians(lng) - 
       radians(-122)) + 
       sin(radians(37)) * 
       sin(radians(lat )))
    ) AS distance 
    FROM markers 
    HAVING distance < 29 and distance > 28 
    ORDER BY distance LIMIT 0, 20;
    

    https://developers.google.com/maps/articles/phpsqlsearch_v3#creating-the-map

  3. ==============================

    3.다음은 PHP에서 구현 내 전체 솔루션입니다.

    다음은 PHP에서 구현 내 전체 솔루션입니다.

    이 용액 http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL에 제시된 바와 같이 화학식 하버 사인을 사용한다.

    하버 사인 공식은 극의 주위에 약점을 경험하는 것을 주목해야한다. 이 문제를 해결하기 위해 큰 원형의 거리 공식 vincenty을 구현하는 방법이 답변 쇼, 그러나 나는 그것이 내 목적을 위해 충분히 좋은이기 때문에 단지 하버 사인을 사용하기로 결정했습니다.

    나는 DECIMAL (11,8)로 DECIMAL과 같은 위도 (10,8)와 경도를 저장하고있다. 희망이 도움이!

    <?PHP
    /**
     * Use the Haversine Formula to display the 100 closest matches to $origLat, $origLon
     * Only search the MySQL table $tableName for matches within a 10 mile ($dist) radius.
     */
    include("./assets/db/db.php"); // Include database connection function
    $db = new database(); // Initiate a new MySQL connection
    $tableName = "db.table";
    $origLat = 42.1365;
    $origLon = -71.7559;
    $dist = 10; // This is the maximum distance (in miles) away from $origLat, $origLon in which to search
    $query = "SELECT name, latitude, longitude, 3956 * 2 * 
              ASIN(SQRT( POWER(SIN(($origLat - latitude)*pi()/180/2),2)
              +COS($origLat*pi()/180 )*COS(latitude*pi()/180)
              *POWER(SIN(($origLon-longitude)*pi()/180/2),2))) 
              as distance FROM $tableName WHERE 
              longitude between ($origLon-$dist/cos(radians($origLat))*69) 
              and ($origLon+$dist/cos(radians($origLat))*69) 
              and latitude between ($origLat-($dist/69)) 
              and ($origLat+($dist/69)) 
              having distance < $dist ORDER BY distance limit 100"; 
    $result = mysql_query($query) or die(mysql_error());
    while($row = mysql_fetch_assoc($result)) {
        echo $row['name']." > ".$row['distance']."<BR>";
    }
    mysql_close($db);
    ?>
    
    <?PHP
    /**
     * Class to initiate a new MySQL connection based on $dbInfo settings found in dbSettings.php
     *
     * @example $db = new database(); // Initiate a new database connection
     * @example mysql_close($db); // close the connection
     */
    class database{
        protected $databaseLink;
        function __construct(){
            include "dbSettings.php";
            $this->database = $dbInfo['host'];
            $this->mysql_user = $dbInfo['user'];
            $this->mysql_pass = $dbInfo['pass'];
            $this->openConnection();
            return $this->get_link();
        }
        function openConnection(){
        $this->databaseLink = mysql_connect($this->database, $this->mysql_user, $this->mysql_pass);
        }
    
        function get_link(){
        return $this->databaseLink;
        }
    }
    ?>
    
    <?php
    $dbInfo = array(
        'host'      => "localhost",
        'user'      => "root",
        'pass'      => "password"
    );
    ?>
    

    위의 게시 된 "지리적 거리 - 검색 -와 - MySQL은"기사에 의해 제안 MySQL의 저장 프로 시저를 사용하여 성능을 향상하는 것이 가능하다.

    나는 ~ 17,000 곳의 데이터베이스와 쿼리 실행 시간은 0.054 초입니다 있습니다.

  4. ==============================

    4.당신이 나 같은 게으른 그냥 경우에, 여기 등 다른 답변에서 합병 솔루션입니다.

    당신이 나 같은 게으른 그냥 경우에, 여기 등 다른 답변에서 합병 솔루션입니다.

    set @orig_lat=37.46; 
    set @orig_long=-122.25; 
    set @bounding_distance=1;
    
    SELECT
    *
    ,((ACOS(SIN(@orig_lat * PI() / 180) * SIN(`lat` * PI() / 180) + COS(@orig_lat * PI() / 180) * COS(`lat` * PI() / 180) * COS((@orig_long - `long`) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS `distance` 
    FROM `cities` 
    WHERE
    (
      `lat` BETWEEN (@orig_lat - @bounding_distance) AND (@orig_lat + @bounding_distance)
      AND `long` BETWEEN (@orig_long - @bounding_distance) AND (@orig_long + @bounding_distance)
    )
    ORDER BY `distance` ASC
    limit 25;
    
  5. ==============================

    5.쉬운 일)

    쉬운 일)

    SELECT * FROM `WAYPOINTS` W ORDER BY
    ABS(ABS(W.`LATITUDE`-53.63) +
    ABS(W.`LONGITUDE`-9.9)) ASC LIMIT 30;
    

    그냥 필요한 사람과 좌표를 교체합니다. 값은 이중으로 저장해야합니다. 이 IST 작업의 MySQL 5.x의 예.

    건배

  6. ==============================

    6.당신은 하버 사인 공식 같은 것을 찾고 있습니다. 뿐만 아니라 여기를 참조하십시오.

    당신은 하버 사인 공식 같은 것을 찾고 있습니다. 뿐만 아니라 여기를 참조하십시오.

    이 다른 것입니다 그러나 이것은 가장 일반적으로 인용이다.

    당신이 훨씬 더 강력한 무언가를 찾고 있다면, 당신은 당신의 데이터베이스의 GIS 기능을보고 할 수 있습니다. 그들은 점 (시) 주어진 다각형 (지역, 국가, 대륙) 내에 표시할지 여부를 알려주 같은 몇 가지 멋진 물건을 할 수있어.

  7. ==============================

    7.기사에 따라이 코드를 확인 지리적 거리 - 검색 -와 - MySQL은 :

    기사에 따라이 코드를 확인 지리적 거리 - 검색 -와 - MySQL은 :

    예 : 10 마일 반경 내 현재 위치로 (10 개) 가까운 호텔을 찾을 수 :

    #Please notice that (lat,lng) values mustn't be negatives to perform all calculations
    
    set @my_lat=34.6087674878572; 
    set @my_lng=58.3783670308302;
    set @dist=10; #10 miles radius
    
    SELECT dest.id, dest.lat, dest.lng,  3956 * 2 * ASIN(SQRT(POWER(SIN((@my_lat -abs(dest.lat)) * pi()/180 / 2),2) + COS(@my_lat * pi()/180 ) * COS(abs(dest.lat) *  pi()/180) * POWER(SIN((@my_lng - abs(dest.lng)) *  pi()/180 / 2), 2))
    ) as distance
    FROM hotel as dest
    having distance < @dist
    ORDER BY distance limit 10;
    
    #Also notice that distance are expressed in terms of radius.
    
  8. ==============================

    8.이 시도, 그것은 (50km 이내) 제공 좌표에 가장 가까운 점을 보여줍니다. 그것은 완벽하게 작동합니다 :

    이 시도, 그것은 (50km 이내) 제공 좌표에 가장 가까운 점을 보여줍니다. 그것은 완벽하게 작동합니다 :

    SELECT m.name,
        m.lat, m.lon,
        p.distance_unit
                 * DEGREES(ACOS(COS(RADIANS(p.latpoint))
                 * COS(RADIANS(m.lat))
                 * COS(RADIANS(p.longpoint) - RADIANS(m.lon))
                 + SIN(RADIANS(p.latpoint))
                 * SIN(RADIANS(m.lat)))) AS distance_in_km
    FROM <table_name> AS m
    JOIN (
          SELECT <userLat> AS latpoint, <userLon> AS longpoint,
                 50.0 AS radius, 111.045 AS distance_unit
         ) AS p ON 1=1
    WHERE m.lat
    BETWEEN p.latpoint  - (p.radius / p.distance_unit)
        AND p.latpoint  + (p.radius / p.distance_unit)
        AND m.lon BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
        AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
    ORDER BY distance_in_km
    

    그냥 로 변경합니다.

    현재이 솔루션에 대한 자세한 내용을보실 수 있습니다 : http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

  9. ==============================

    9.

    simpledb.execSQL("CREATE TABLE IF NOT EXISTS " + tablename + "(id INTEGER PRIMARY KEY   AUTOINCREMENT,lat double,lng double,address varchar)");
                simpledb.execSQL("insert into '" + tablename + "'(lat,lng,address)values('22.2891001','70.780154','craftbox');");
                simpledb.execSQL("insert into '" + tablename + "'(lat,lng,address)values('22.2901396','70.7782428','kotecha');");//22.2904718 //70.7783906
                simpledb.execSQL("insert into '" + tablename + "'(lat,lng,address)values('22.2863155','70.772108','kkv Hall');");
                simpledb.execSQL("insert into '" + tablename + "'(lat,lng,address)values('22.275993','70.778076','nana mava');");
                simpledb.execSQL("insert into '" + tablename + "'(lat,lng,address)values('22.2667148','70.7609386','Govani boys hostal');");
    
    
        double curentlat=22.2667258;  //22.2677258
        double curentlong=70.76096826;//70.76096826
    
        double curentlat1=curentlat+0.0010000;
        double curentlat2=curentlat-0.0010000;
    
        double curentlong1=curentlong+0.0010000;
        double curentlong2=curentlong-0.0010000;
    
        try{
    
            Cursor c=simpledb.rawQuery("select * from '"+tablename+"' where (lat BETWEEN '"+curentlat2+"' and '"+curentlat1+"') or (lng BETWEEN         '"+curentlong2+"' and '"+curentlong1+"')",null);
    
            Log.d("SQL ", c.toString());
            if(c.getCount()>0)
            {
                while (c.moveToNext())
                {
                    double d=c.getDouble(1);
                    double d1=c.getDouble(2);
    
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    
  10. ==============================

    10.질문에 대한 원래의 대답은 좋다,하지만 지금은 기능보다는 복잡한 쿼리를하고 내장 사용할 수 있도록 MySQL의 (에 MySQL은 5.7.6) 지원 지리적 쿼리의 최신 버전.

    질문에 대한 원래의 대답은 좋다,하지만 지금은 기능보다는 복잡한 쿼리를하고 내장 사용할 수 있도록 MySQL의 (에 MySQL은 5.7.6) 지원 지리적 쿼리의 최신 버전.

    이제 뭔가를 할 수 있습니다 :

    select *, ST_Distance_Sphere( point ('input_longitude', 'input_latitude'), 
                                  point(longitude, latitude)) * .000621371192 
              as `distance_in_miles` 
      from `TableName`
    having `distance_in_miles` <= 'input_max_distance'
     order by `distance_in_miles` asc
    

    당신이 KM을 원한다면 결과 마일 0.0001 대신 0.000621371192을의 사용 대신 미터에 반환

    MySQL의 워드 프로세서는 여기에 있습니다

  11. ==============================

    11.당신이 거리에 바인딩 일부와 가장 가까운 이웃 검색을 수행 할 것 같은데. SQL 내가 알고 지금까지처럼 이런 일을 지원하지 않습니다 그리고 당신은 같은 R-트리 또는 KD-트리로 다른 데이터 구조를 사용해야합니다.

    당신이 거리에 바인딩 일부와 가장 가까운 이웃 검색을 수행 할 것 같은데. SQL 내가 알고 지금까지처럼 이런 일을 지원하지 않습니다 그리고 당신은 같은 R-트리 또는 KD-트리로 다른 데이터 구조를 사용해야합니다.

  12. ==============================

    12.나의 가장 가까운 사용자를 찾기 :

    나의 가장 가까운 사용자를 찾기 :

    미터의 거리

    Vincenty의 공식에 본사를 둔

    나는 사용자 테이블이 있습니다 :

    +----+-----------------------+---------+--------------+---------------+
    | id | email                 | name    | location_lat | location_long |
    +----+-----------------------+---------+--------------+---------------+
    | 13 | xxxxxx@xxxxxxxxxx.com | Isaac   | 17.2675625   | -97.6802361   |
    | 14 | xxxx@xxxxxxx.com.mx   | Monse   | 19.392702    | -99.172596    |
    +----+-----------------------+---------+--------------+---------------+
    

    SQL :

    -- my location:  lat   19.391124   -99.165660
    SELECT 
    (ATAN(
        SQRT(
            POW(COS(RADIANS(users.location_lat)) * SIN(RADIANS(users.location_long) - RADIANS(-99.165660)), 2) +
            POW(COS(RADIANS(19.391124)) * SIN(RADIANS(users.location_lat)) - 
           SIN(RADIANS(19.391124)) * cos(RADIANS(users.location_lat)) * cos(RADIANS(users.location_long) - RADIANS(-99.165660)), 2)
        )
        ,
        SIN(RADIANS(19.391124)) * 
        SIN(RADIANS(users.location_lat)) + 
        COS(RADIANS(19.391124)) * 
        COS(RADIANS(users.location_lat)) * 
        COS(RADIANS(users.location_long) - RADIANS(-99.165660))
     ) * 6371000) as distance,
    users.id
    FROM users
    ORDER BY distance ASC
    

    지구의 반경 : 6371000 (미터)

  13. ==============================

    13.당신 같은 소리는 PostGIS와, Spatialite, SQL 서버 2008, 또는 Oracle 공간을 사용해야합니다. 그들은 모든 공간 SQL과 당신이 질문에 대답 할 수 있습니다.

    당신 같은 소리는 PostGIS와, Spatialite, SQL 서버 2008, 또는 Oracle 공간을 사용해야합니다. 그들은 모든 공간 SQL과 당신이 질문에 대답 할 수 있습니다.

  14. ==============================

    14.극단적 인 경우에는이 방법이 실패하지만, 성능, I의 한은 삼각법을 생략하고 간단하게 대각선 제곱을 계산.

    극단적 인 경우에는이 방법이 실패하지만, 성능, I의 한은 삼각법을 생략하고 간단하게 대각선 제곱을 계산.

  15. ==============================

    15.MS SQL 판 여기 :

    MS SQL 판 여기 :

            DECLARE @SLAT AS FLOAT
            DECLARE @SLON AS FLOAT
    
            SET @SLAT = 38.150785
            SET @SLON = 27.360249
    
            SELECT TOP 10 [LATITUDE], [LONGITUDE], SQRT(
                POWER(69.1 * ([LATITUDE] - @SLAT), 2) +
                POWER(69.1 * (@SLON - [LONGITUDE]) * COS([LATITUDE] / 57.3), 2)) AS distance
            FROM [TABLE] ORDER BY 3
    
  16. ==============================

    16.이 문제는 모든 매우 어려운 일이 아니다,하지만 당신은 그것을 최적화해야하는 경우는 더 복잡해진다.

    이 문제는 모든 매우 어려운 일이 아니다,하지만 당신은 그것을 최적화해야하는 경우는 더 복잡해진다.

    나는이 무슨 뜻인지, 당신이 당신의 데이터베이스 또는 1 억 100 개 위치를해야합니까? 그것은 큰 차이를 만든다.

    위치의 수가 작은 경우, 단지 수행하여 SQL의 코드로 그들을 얻을 ->

    Select * from Location
    

    당신이 코드로 얻을되면, 사이의 거리 각 위도 / 경도와 하버 사인 공식 원본 및 종류를 계산합니다.

  17. from https://stackoverflow.com/questions/2234204/find-nearest-latitude-longitude-with-an-sql-query by cc-by-sa and MIT license