sql >> Databáze >  >> RDS >> Mysql

Třídění dotazů MySQL podle zeměpisné šířky/délky

Pamatujete si Pythagora?

$sql = "SELECT * FROM table 
    WHERE lon BETWEEN '$minLon' AND '$maxLon' 
      AND lat BETWEEN '$minLat' AND '$maxLat'
    ORDER BY (POW((lon-$lon),2) + POW((lat-$lat),2))";

Technicky jde o druhou mocninu vzdálenosti místo skutečné vzdálenosti, ale protože ji používáte pouze pro třídění, na tom nezáleží.

To používá vzorec rovinné vzdálenosti, který by měl být dobrý na malé vzdálenosti.

VŠAK:

Pokud chcete být přesnější nebo použít delší vzdálenosti, použijte tento vzorec pro vzdálenosti velkých kruhů v radiánech :

dist = acos[ sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lng1-lng2) ]

(Chcete-li získat vzdálenost ve skutečných jednotkách místo v radiánech, vynásobte ji poloměrem Země. To však není nutné pro účely objednávky.)

Výpočetní stroj MySQL předpokládá, že zeměpisná šířka a délka jsou v radiánech, takže pokud jsou uloženy ve stupních (a pravděpodobně je), budete muset každou hodnotu vynásobit pi/180, přibližně 0,01745:

$sf = 3.14159 / 180; // scaling factor
$sql = "SELECT * FROM table 
    WHERE lon BETWEEN '$minLon' AND '$maxLon' 
      AND lat BETWEEN '$minLat' AND '$maxLat'
    ORDER BY ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))";

nebo dokonce:

$sf = 3.14159 / 180; // scaling factor
$er = 6350; // earth radius in miles, approximate
$mr = 100; // max radius
$sql = "SELECT * FROM table 
    WHERE $mr >= $er * ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))
    ORDER BY ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))";


  1. Django:Používání vlastních nezpracovaných vložek SQL s exekutory a MySQL

  2. Význam n:m a 1:n v návrhu databáze

  3. Měly by být nové sloupce indexu v klíči nebo zahrnuty?

  4. Deset nejlepších nástrojů GUI MySQL