Mysql
 sql >> Database >  >> RDS >> Mysql

calcoli della distanza nelle query MySQL

Opzione 1:esegui il calcolo sul database passando a un database che supporta GeoIP.

Opzione 2:eseguire il calcolo sul database utilizzando una procedura memorizzata come questa:

CREATE FUNCTION calcDistance (latA double, lonA double, latB double, LonB double)
    RETURNS double DETERMINISTIC
BEGIN
    SET @RlatA = radians(latA);
    SET @RlonA = radians(lonA);
    SET @RlatB = radians(latB);
    SET @RlonB = radians(LonB);
    SET @deltaLat = @RlatA - @RlatB;
    SET @deltaLon = @RlonA - @RlonB;
    SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) +
    COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2);
    RETURN 2 * ASIN(SQRT(@d)) * 6371.01;
END//

Se hai un indice di latitudine e longitudine nel tuo database, puoi ridurre il numero di calcoli che devono essere calcolati elaborando un riquadro di delimitazione iniziale in PHP ($minLat, $maxLat, $minLong e $maxLong) e limitando le righe in un sottoinsieme delle tue voci in base a quello (DOVE latitudine TRA $minLat E $maxLat E longitudine TRA $minLong E $maxLong). Quindi MySQL deve solo eseguire il calcolo della distanza per quel sottoinsieme di righe.

Se stai semplicemente usando una procedura memorizzata per calcolare la distanza), SQL deve comunque esaminare ogni record nel tuo database e calcolare la distanza per ogni record nel tuo database prima di poter decidere se restituire quella riga o scartarla .

Poiché il calcolo è relativamente lento da eseguire, sarebbe meglio se potessi ridurre l'insieme di righe che devono essere calcolate, eliminando le righe che chiaramente cadranno al di fuori della distanza richiesta, in modo da eseguire solo il costoso calcolo per un numero inferiore di righe.

Se consideri che quello che stai facendo è fondamentalmente disegnare un cerchio su una mappa, centrato sul tuo punto iniziale e con un raggio di distanza; quindi la formula identifica semplicemente quali righe rientrano in quel cerchio... ma deve comunque controllare ogni singola riga.

Usare un rettangolo di selezione è come disegnare prima un quadrato sulla mappa con i bordi sinistro, destro, superiore e inferiore alla distanza appropriata dal nostro punto centrale. Il nostro cerchio verrà quindi disegnato all'interno di quella casella, con i punti più a nord, est, sud e ovest del cerchio che toccano i bordi della casella. Alcune righe cadranno al di fuori di quella casella, quindi SQL non si preoccupa nemmeno di provare a calcolare la distanza per quelle righe. Calcola solo la distanza per quelle righe che rientrano nel riquadro di delimitazione per vedere se rientrano anche all'interno del cerchio.

All'interno del tuo PHP (supponiamo che tu stia eseguendo PHP dal nome della variabile $), possiamo utilizzare un calcolo molto semplice che calcola la latitudine e la longitudine minima e massima in base alla nostra distanza, quindi impostare quei valori nella clausola WHERE del tuo SQL dichiarazione. Questa è effettivamente la nostra scatola e tutto ciò che non rientra in essa viene automaticamente scartato senza che sia necessario calcolarne effettivamente la distanza.

C'è una buona spiegazione di questo (con codice PHP) su Movable Type sito web questa dovrebbe essere una lettura essenziale per chiunque abbia intenzione di fare qualsiasi lavoro di GeoPositioning in PHP.

MODIFICA Il valore 6371.01 nella procedura memorizzata calcDistance è il moltiplicatore per fornire un risultato restituito in chilometri. Usa moltiplicatori alternativi appropriati se vuoi ottenere miglia, miglia nautiche, metri, qualunque cosa