sql >> Databasteknik >  >> RDS >> Mysql

Hitta avståndet mellan två punkter med hjälp av latitud och longitud i mysql

Jag tror att din fråga säger att du har city värden för de två städerna mellan vilka du vill beräkna avståndet.

Denna fråga kommer att göra jobbet åt dig och ger avståndet i km. Den använder den sfäriska cosinuslagformeln.

Lägg märke till att du kopplar tabellen till sig själv så att du kan hämta två koordinatpar för beräkningen.

SELECT a.city AS from_city, b.city AS to_city, 
   111.111 *
    DEGREES(ACOS(LEAST(1.0, COS(RADIANS(a.Latitude))
         * COS(RADIANS(b.Latitude))
         * COS(RADIANS(a.Longitude - b.Longitude))
         + SIN(RADIANS(a.Latitude))
         * SIN(RADIANS(b.Latitude))))) AS distance_in_km
  FROM city AS a
  JOIN city AS b ON a.id <> b.id
 WHERE a.city = 3 AND b.city = 7

Lägg märke till att konstanten 111.1111 är antalet kilometer per latitud, baserat på den gamla Napoleon-definitionen av mätaren som en tiotusendel av avståndet från ekvatorn till polen. Den definitionen är tillräckligt nära för platssökningsarbete.

Om du vill ha lagstadgade miles istället för kilometer, använd 69.0 istället.

http://sqlfiddle.com/#!9/21e06/412/0

Om du letar efter närliggande punkter kan du bli frestad att använda en klausul ungefär så här:

   HAVING distance_in_km < 10.0    /* slow ! */
    ORDER BY distance_in_km DESC

Det är (som vi säger nära Boston MA, USA) grymt långsamt.

I så fall måste du använda en bounding box-beräkning. Se den här texten om hur du gör det. http://www.plumislandmedia.net/mysql/haversine-mysql- närmaste-loc/

Formeln innehåller en LEAST() fungera. Varför? Eftersom ACOS() funktionen ger ett fel om dess argument till och med är något större än 1. När de två punkterna i fråga är mycket nära varandra kommer uttrycket med COS() och SIN() beräkningar kan ibland ge ett värde som är något större än 1 på grund av floating-point epsilon (oexakthet ). LEAST(1.0, dirty-great-expression) call hanterar det problemet.

Det finns ett bättre sätt, en formel av Thaddeus Vincenty . Den använder ATAN2() snarare än ACOS() så det är mindre mottagligt för epsilon-problem.



  1. Hur kör man en lagrad procedur i sql-servern varje timme?

  2. Visa SQL Server Agent jobbhistorik med SSMS

  3. MySQL MONTHNAME() från siffror

  4. Vad är logisk OCH operatör i SQL Server - SQL Server / TSQL Tutorial Del 120