sql >> Database >  >> RDS >> Mysql

afstandsberekeningen in mysql-query's

Optie 1:Voer de berekening uit op de database door over te schakelen naar een database die GeoIP ondersteunt.

Optie 2:Voer de berekening uit op de database met behulp van een opgeslagen procedure zoals deze:

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//

Als u een index op lengte- en breedtegraad in uw database heeft, kunt u het aantal berekeningen dat moet worden berekend verminderen door een eerste begrenzingsvak in PHP ($minLat, $maxLat, $minLong en $maxLong) uit te werken en te beperken de rijen naar een subset van uw vermeldingen op basis daarvan (WAAR breedtegraad TUSSEN $minLat EN $maxLat EN lengtegraad TUSSEN $minLong EN $maxLong). Dan hoeft MySQL alleen de afstandsberekening uit te voeren voor die subset van rijen.

Als u gewoon een opgeslagen procedure gebruikt om de afstand te berekenen), moet SQL nog steeds door elk record in uw database kijken en de afstand voor elk record in uw database berekenen voordat het kan beslissen of die rij moet worden geretourneerd of verwijderd. .

Omdat de berekening relatief traag is om uit te voeren, zou het beter zijn als u de reeks rijen die moet worden berekend, zou kunnen verminderen, en rijen zou elimineren die duidelijk buiten de vereiste afstand vallen, zodat we alleen de dure berekening uitvoeren voor een kleiner aantal rijen.

Als je bedenkt dat je eigenlijk een cirkel op een kaart tekent, gecentreerd op je beginpunt en met een afstandsstraal; dan identificeert de formule eenvoudig welke rijen binnen die cirkel vallen... maar het moet nog steeds elke rij controleren.

Het gebruik van een selectiekader is alsof u eerst een vierkant op de kaart tekent met de linker-, rechter-, boven- en onderrand op de juiste afstand van ons middelpunt. Onze cirkel wordt dan binnen dat kader getekend, waarbij de meest noordelijke, oostelijke, zuidelijke en westelijke punten op de cirkel de randen van de doos raken. Sommige rijen vallen buiten dat vak, dus SQL neemt niet eens de moeite om de afstand voor die rijen te berekenen. Het berekent alleen de afstand voor die rijen die binnen het selectiekader vallen om te zien of ze ook binnen de cirkel vallen.

Binnen je PHP (denk dat je PHP draait vanaf de $ variabele naam), kunnen we een heel eenvoudige berekening gebruiken die de minimale en maximale lengte- en breedtegraad uitrekent op basis van onze afstand, en die waarden vervolgens in de WHERE-clausule van je SQL in te stellen uitspraak. Dit is in feite onze doos, en alles wat daarbuiten valt, wordt automatisch weggegooid zonder dat het nodig is om de afstand daadwerkelijk te berekenen.

Er is een goede uitleg hiervan (met PHP-code) op de Movable Type website dat zou essentieel leesvoer moeten zijn voor iedereen die van plan is om GeoPositioning-werk in PHP te doen.

BEWERKEN De waarde 6371.01 in de opgeslagen procedure calcDistance is de vermenigvuldiger om u een geretourneerd resultaat in kilometers te geven. Gebruik geschikte alternatieve vermenigvuldigers als je wilt resulteren in mijlen, zeemijlen, meters, wat dan ook



  1. De meest voorkomende waarde selecteren uit relatie - SQL-instructie

  2. Hoe krijg ik een correcte dump met mysqldump en single-transactie wanneer DDL tegelijkertijd wordt gebruikt?

  3. Voorbeeld van het gebruik van bind_result versus get_result

  4. kan geen verbinding maken met mysql met php