or que essa função armazenada do MySQL fornece resultados diferentes do que fazer o cálculo na consult

Esta é uma pergunta sobre o cálculo da distância entre dois pontos de latitude e longitude na Terra usando uma fórmula de Haversine, para uso em projetos nos quais você precisa ter a função 'encontrar o meu mais próximo'

fórmula haversine é bem discutida e resolvida no MySQL emesta postage.

Eu pergunteiessa questã sobre transformá-lo em uma função armazenada para que esteja disponível para projetos futuros sem precisar pesquisar, lembrar ou redigitar a fórmula em sua forma extens

É tudo de bom. Exceto que minha função difere nos resultados (levemente) apenas de digitar a fórmula diretamente na consulta, todas as outras coisas sendo iguais. Por que é isso

Então, aqui está a função que escrevi:

DELIMITER $

DROP FUNCTION IF EXISTS haversine $

CREATE FUNCTION `haversine`
    (fromLatitude FLOAT,
     fromLongitude FLOAT,
     toLatitude FLOAT,
     toLongitude FLOAT,
     unit VARCHAR(20)
     )
    RETURNS FLOAT
    DETERMINISTIC    
    COMMENT 'Returns the distance on the Earth between two known points of longitude and latitude'
    BEGIN
    DECLARE radius FLOAT;
    DECLARE distance FLOAT;

    IF unit = 'MILES' THEN SET radius = '3959';
    ELSEIF (unit = 'NAUTICAL_MILES' OR unit='NM') THEN SET radius = '3440.27694';   
    ELSEIF (unit = 'YARDS' OR unit='YD') THEN SET radius = '6967840';
    ELSEIF (unit = 'FEET' OR unit='FT') THEN SET radius = '20903520';
    ELSEIF (unit = 'KILOMETRES' OR unit='KILOMETERS' OR unit='KM') THEN SET radius = '6371.3929';
    ELSEIF (unit = 'METRES' OR UNIT='METERS' OR unit='M') THEN SET radius = '6371392.9';
    ELSE SET radius = '3959'; /* default to miles */
    END IF;

    SET distance = (radius * ACOS(COS(RADIANS(fromLatitude)) * COS(RADIANS(toLatitude)) * COS(RADIANS(toLongitude) - RADIANS(fromLongitude)) + SIN(RADIANS(fromLatitude)) * SIN(RADIANS(toLatitude))));

    RETURN distance;
    END$

DELIMITER ;

Aqui está um conjunto de consultas de teste para encontrar a distância entre o London Eye e o Palácio de Buckingham, apenas por exemplo. Obviamente, normalmente você substitui o destino por campos do seu banco de dados de 'itens' localizados geograficamente com os quais deseja comparar.

SET @milesModifier = 3959;

SET @myLat = 51.503228;
SET @myLong = -0.119703;

SET @destLat = 51.501267;  
SET @destLong = -0.142697;

SELECT  @kilometerModifier AS radius,
    @myLat AS myLat,
    @myLong AS myLong,
    @destLat AS destLat,
    @destLong AS destLong,
    (@milesModifier * ACOS(COS(RADIANS(@myLat)) * COS(RADIANS(@destLat)) * COS(RADIANS(@destLong) - RADIANS(@myLong)) + SIN(RADIANS(@myLat)) * SIN(RADIANS(@destLat)))) AS longFormat,
    haversine(@myLat,@myLong,@destLat,@destLong,'MILES') AS distanceMiles,
    haversine(@myLat,@myLong,@destLat,@destLong,'NAUTICAL_MILES') AS distanceNautical,
    haversine(@myLat,@myLong,@destLat,@destLong,'KM') AS distanceKm,
    haversine(@myLat,@myLong,@destLat,@destLong,'METRES') AS distanceMetres,    
    haversine(@myLat,@myLong,@destLat,@destLong,'YARDS') AS distanceYards,
    haversine(@myLat,@myLong,@destLat,@destLong,'FEET') AS distanceFeet,
    haversine(@myLat,@myLong,@destLat,@destLong,'') AS distanceDefault

No exemplo, estamos usando milhas - então definimos o raio @ milesModifier no teste,rai na função) para 3959 exatament

O resultado que voltei foi interessante (no MySQL 5.2.6 community edition), destaques:

| longFormat       | distanceMiles   |
|------------------|-----------------|
| 0.99826000106148 | 0.9982578754425 |

longFormat é a matemática feita na consulta, distanceMiles é o resultado da função.

Os resultados são diferentes ... OK, então é uma insignificância quanto ao uso da função em um projeto, mas estou interessado em saber como a mesma fórmula dentro ou fora da função tem resultados diferente

Acho que isso tem a ver com os comprimentos do FLOAT - eles não estão especificados na função, tentei especificá-los (até 30,15) para dar muito espaço para todas as figuras que tenho e as saída que eu espero - mas os resultados ainda diferem um pouco.

questionAnswers(1)

yourAnswerToTheQuestion