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

afstandsberegninger i mysql-forespørgsler

Mulighed 1:Udfør beregningen på databasen ved at skifte til en database, der understøtter GeoIP.

Mulighed 2:Udfør beregningen på databasen ved hjælp af en lagret procedure som denne:

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

Hvis du har et indeks på bredde- og længdegrad i din database, kan du reducere antallet af beregninger, der skal beregnes ved at udarbejde en indledende afgrænsningsramme i PHP ($minLat, $maxLat, $minLong og $maxLong) og begrænse rækkerne til en undergruppe af dine indtastninger baseret på det (HVOR breddegrad MELLEM $minLat OG $maxLat OG længdegrad MELLEM $minLong OG $maxLong). Så behøver MySQL kun at udføre afstandsberegningen for den delmængde af rækker.

Hvis du blot bruger en lagret procedure til at beregne afstanden), så skal SQL stadig se gennem hver post i din database og beregne afstanden for hver post i din database, før den kan beslutte, om den skal returnere den række eller kassere den. .

Fordi beregningen er relativt langsom at udføre, ville det være bedre, hvis du kunne reducere antallet af rækker, der skal beregnes, og eliminere rækker, der klart falder uden for den påkrævede afstand, så vi kun udfører den dyre beregning for et mindre antal rækker.

Hvis du tænker på, at det du laver dybest set er at tegne en cirkel på et kort, centreret på dit første punkt og med en afstandsradius; så identificerer formlen ganske enkelt, hvilke rækker der falder inden for den cirkel... men den skal stadig kontrollere hver enkelt række.

At bruge en afgrænsningsramme er som at tegne en firkant på kortet først med venstre, højre, øverste og nederste kanter i passende afstand fra vores midtpunkt. Vores cirkel vil derefter blive tegnet inden for det felt, med de nordligste, østligste, sydligste og vestligste punkter på cirklen, der berører boksens grænser. Nogle rækker vil falde uden for den boks, så SQL gider ikke engang at prøve at beregne afstanden for disse rækker. Den beregner kun afstanden for de rækker, der falder inden for afgrænsningsrammen for at se, om de også falder inden for cirklen.

Inden for din PHP (gæt du kører PHP fra $-variabelnavnet), kan vi bruge en meget simpel beregning, der beregner minimum og maksimum bredde- og længdegrad baseret på vores afstand, og derefter indstille disse værdier i WHERE-sætningen i din SQL udmelding. Dette er faktisk vores boks, og alt, der falder uden for den, kasseres automatisk uden behov for faktisk at beregne afstanden.

Der er en god forklaring på dette (med PHP-kode) på Movable Type websted det burde være vigtig læsning for enhver, der planlægger at udføre GeoPositioning arbejde i PHP.

REDIGER Værdien 6371.01 i calcDistance lagrede procedure er multiplikatoren for at give dig et returneret resultat i kilometer. Brug passende alternative multiplikatorer, hvis du ønsker at resultere i miles, sømil, meter, hvad som helst



  1. PreparedStatement ignorerer parametre i forespørgslen:java.sql.SQLException:Parameterindeks uden for område (1> antal parametre, som er 0)

  2. Indsæt og sæt værdi med max()+1 problemer

  3. Hvordan bruger man outer full join i laravel 5.0?

  4. LEAST() Funktion i PostgreSQL