[SQL] SQL 쿼리와 가까운 위도 / 경도 찾기
SQLSQL 쿼리와 가까운 위도 / 경도 찾기
내가 위도와 경도가 있고 내가 그 거리가 지정된 하나보다 더 얻는 경우에, 거리가 가까운 위도와 경도를 가지고있는 데이터베이스에서 레코드를 끌어하고자, 다음을 검색하지 않습니다.
테이블 구조 :
id
latitude
longitude
place name
city
country
state
zip
sealevel
해결법
-
==============================
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.당신은 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.다음은 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.당신이 나 같은 게으른 그냥 경우에, 여기 등 다른 답변에서 합병 솔루션입니다.
당신이 나 같은 게으른 그냥 경우에, 여기 등 다른 답변에서 합병 솔루션입니다.
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.쉬운 일)
쉬운 일)
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.당신은 하버 사인 공식 같은 것을 찾고 있습니다. 뿐만 아니라 여기를 참조하십시오.
당신은 하버 사인 공식 같은 것을 찾고 있습니다. 뿐만 아니라 여기를 참조하십시오.
이 다른 것입니다 그러나 이것은 가장 일반적으로 인용이다.
당신이 훨씬 더 강력한 무언가를 찾고 있다면, 당신은 당신의 데이터베이스의 GIS 기능을보고 할 수 있습니다. 그들은 점 (시) 주어진 다각형 (지역, 국가, 대륙) 내에 표시할지 여부를 알려주 같은 몇 가지 멋진 물건을 할 수있어.
-
==============================
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.이 시도, 그것은 (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.
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.질문에 대한 원래의 대답은 좋다,하지만 지금은 기능보다는 복잡한 쿼리를하고 내장 사용할 수 있도록 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.당신이 거리에 바인딩 일부와 가장 가까운 이웃 검색을 수행 할 것 같은데. SQL 내가 알고 지금까지처럼 이런 일을 지원하지 않습니다 그리고 당신은 같은 R-트리 또는 KD-트리로 다른 데이터 구조를 사용해야합니다.
당신이 거리에 바인딩 일부와 가장 가까운 이웃 검색을 수행 할 것 같은데. SQL 내가 알고 지금까지처럼 이런 일을 지원하지 않습니다 그리고 당신은 같은 R-트리 또는 KD-트리로 다른 데이터 구조를 사용해야합니다.
-
==============================
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.당신 같은 소리는 PostGIS와, Spatialite, SQL 서버 2008, 또는 Oracle 공간을 사용해야합니다. 그들은 모든 공간 SQL과 당신이 질문에 대답 할 수 있습니다.
당신 같은 소리는 PostGIS와, Spatialite, SQL 서버 2008, 또는 Oracle 공간을 사용해야합니다. 그들은 모든 공간 SQL과 당신이 질문에 대답 할 수 있습니다.
-
==============================
14.극단적 인 경우에는이 방법이 실패하지만, 성능, I의 한은 삼각법을 생략하고 간단하게 대각선 제곱을 계산.
극단적 인 경우에는이 방법이 실패하지만, 성능, I의 한은 삼각법을 생략하고 간단하게 대각선 제곱을 계산.
-
==============================
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.이 문제는 모든 매우 어려운 일이 아니다,하지만 당신은 그것을 최적화해야하는 경우는 더 복잡해진다.
이 문제는 모든 매우 어려운 일이 아니다,하지만 당신은 그것을 최적화해야하는 경우는 더 복잡해진다.
나는이 무슨 뜻인지, 당신이 당신의 데이터베이스 또는 1 억 100 개 위치를해야합니까? 그것은 큰 차이를 만든다.
위치의 수가 작은 경우, 단지 수행하여 SQL의 코드로 그들을 얻을 ->
Select * from Location
당신이 코드로 얻을되면, 사이의 거리 각 위도 / 경도와 하버 사인 공식 원본 및 종류를 계산합니다.
from https://stackoverflow.com/questions/2234204/find-nearest-latitude-longitude-with-an-sql-query by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 무작위 SQL에서 행을 선택하려면? (0) | 2020.03.16 |
---|---|
[SQL] COUNT (*) 대 수 (1) 대 수 (PK) : 더 나은 무엇입니까? [복제] (0) | 2020.03.16 |
[SQL] 왜 IN 조건은 SQL에서 "="보다 느린 것입니까? (0) | 2020.03.16 |
[SQL] 어떻게 두 테이블에 MySQL에 합류? (0) | 2020.03.16 |
[SQL] 다중 부분 식별자는 바인딩 수 없습니다 (0) | 2020.03.15 |