Semiverseno en MySQL – Haversine

En este post te voy a mostrar una fórmula de MySQL para calcular la distancia entre dos coordenadas GPS (latitud y longitud) en metros, de modo que podrás calcular la cantidad de metros que existen entre 2 puntos geográficos al hacer consultas SQL.

Debido a que vamos a definir la fórmula como una función de MySQL vas a poder usarla al hacer cualquier operación como SELECT o INSERT.

Vamos a usar la fórmula de Haversine también llamada semiverseno, misma que permite conocer la distancia de círculo máximo entre dos puntos de un globo sabiendo su longitud y su latitud.

Definición de Haversine con MySQL

La siguiente función para calcular la distancia entre 2 coordenadas con MySQL te va a devolver la distancia en metros; obviamente puedes convertirla a kilómetros o metros.

El código SQL es el siguiente:

DELIMITER //

CREATE FUNCTION haversine(lat1 DOUBLE, lon1 DOUBLE, lat2 DOUBLE, lon2 DOUBLE)
RETURNS DOUBLE
DETERMINISTIC
BEGIN
    DECLARE RADIO_TIERRA_EN_KILOMETROS DOUBLE DEFAULT 6371.0;
    DECLARE deltaLongitud DOUBLE;
    DECLARE deltaLatitud DOUBLE;
    DECLARE halfChordLengthSquared DOUBLE;
    DECLARE angularDistanceRadians DOUBLE;
    DECLARE distanciaMetros DOUBLE;

    -- Convertir las coordenadas de grados a radianes
    SET lat1 = RADIANS(lat1);
    SET lon1 = RADIANS(lon1);
    SET lat2 = RADIANS(lat2);
    SET lon2 = RADIANS(lon2);

    -- Calcular las diferencias
    SET deltaLongitud = lon2 - lon1;
    SET deltaLatitud = lat2 - lat1;

    -- Aplicar la fórmula del haversine
    SET halfChordLengthSquared = POW(SIN(deltaLatitud / 2), 2) + COS(lat1) * COS(lat2) * POW(SIN(deltaLongitud / 2), 2);
    SET angularDistanceRadians = 2 * ATAN2(SQRT(halfChordLengthSquared), SQRT(1 - halfChordLengthSquared));
    SET distanciaMetros = RADIO_TIERRA_EN_KILOMETROS * angularDistanceRadians * 1000;  -- Convertir a metros

    RETURN distanciaMetros;
END //

DELIMITER ;

Solo debes ejecutarlo en tu base de datos una vez, y después vas a poder calcular la distancia entre coordenadas con MySQL en cualquier tabla. Incluso puedes probarla sin tabla, por ejemplo:

SELECT haversine(19.416326917410476, -99.12479042256915, 23.097069089850933, -82.35006433419622);

La salida de esa consulta será 1784668.3798590573 lo cual es correcto según mi otro post de Haversine con JS. No olvides que en este caso la salida está en metros.

Usando Semiverseno con MySQL usando tabla

A continuación se presenta un ejemplo de una consulta usando esta fórmula:

INSERT INTO
    ubicaciones_conductores (
        id_conductor, fecha,
		latitud, longitud, precision_horizontal,
        id_ruta_destino, id_ruta_origen,
        id_parada_mas_cercana, distancia_parada_mas_cercana
    )
SELECT ?, ?,
?, ?, ?,
?, ?,
    subconsulta.id, subconsulta.distancia
FROM
    (
        SELECT
            id,
            haversine(latitud, longitud, ?, ?) AS distancia
        FROM
            paradas
        ORDER BY
            distancia ASC
        LIMIT
            1
    ) AS subconsulta;

Si quisieras un ejemplo más sencillo podrías hacer algo como:

SELECT haversine(lat1, lon1, lat2, lot2) AS distancia FROM tabla;

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *