Calcolo dinamico della distanza tra due punti geografici in SQL Server con Stored Procedure

Calcolo dinamico della distanza tra due punti geografici in SQL Server con Stored Procedure

Marco Puccio

Introduzione

Nel mondo moderno, le applicazioni che utilizzano dati geografici sono sempre più comuni: servizi di food delivery, app di navigazione, logistica, e-commerce con selezione dei punti di ritiro, e molte altre. Un elemento fondamentale è il calcolo preciso della distanza tra due punti sulla superficie terrestre. SQL Server fornisce strumenti nativi per gestire dati geospaziali tramite i tipi di dato GEOGRAPHYGEOMETRY, rendendo possibile eseguire operazioni complesse direttamente nel database.

In questo articolo approfondiremo il calcolo della distanza tra due coordinate geografiche usando il tipo GEOGRAPHY e la funzione STDistance(), implementando una stored procedure dinamica e spiegando ogni passaggio nel dettaglio. Inoltre, vedremo come integrare queste soluzioni in contesti reali, come ottimizzarle per prestazioni elevate e cosa tenere in considerazione quando si lavora con dati geospaziali.

Tipi di dati spaziali in SQL Server

SQL Server offre due tipi principali per rappresentare dati spaziali:

  • GEOGRAPHY: Modella la superficie terrestre come una sfera, tenendo conto della curvatura terrestre. È perfetto per coordinate GPS (latitudine e longitudine).

  • GEOMETRY: Usa un sistema cartesiano plano, adatto a mappe tecniche, disegni architettonici, e scenari locali dove la curvatura terrestre è trascurabile.

Nel nostro scenario, dove trattiamo distanze geografiche reali tra punti su scala cittadina, regionale o nazionale, è obbligatorio usare GEOGRAPHY per ottenere risultati corretti.

SRID e coordinate geografiche

L'SRID (Spatial Reference Identifier) più comunemente utilizzato è il 4326, che fa riferimento al sistema di coordinate WGS 84 (utilizzato dai GPS di tutto il mondo). Ogni punto GEOGRAPHY in SQL Server deve specificare l'SRID corretto per assicurare accuratezza nei calcoli.

Rappresentare un punto geografico

Per creare un punto geografico in SQL Server, si usa la funzione:

GEOGRAPHY::Point(latitudine, longitudine, SRID)

Esempio:

DECLARE @p GEOGRAPHY = GEOGRAPHY::Point(38.1157, 13.3615, 4326); -- Palermo

Questo crea un punto geospaziale nel formato corretto. Si noti che la latitudine viene indicata per prima, seguita dalla longitudine. L'inversione di questi parametri è un errore comune che può portare a risultati errati.

Calcolare la distanza tra due punti

Una volta creati due oggetti GEOGRAPHY, è possibile calcolare la distanza con il metodo STDistance, che restituisce il risultato in metri.

DECLARE @p1 GEOGRAPHY = GEOGRAPHY::Point(38.1157, 13.3615, 4326);
DECLARE @p2 GEOGRAPHY = GEOGRAPHY::Point(37.5079, 15.0830, 4326);

SELECT @p1.STDistance(@p2) AS DistanzaInMetri;

Il metodo STDistance utilizza algoritmi interni per calcolare la distanza sulla superficie di un ellissoide terrestre. Il risultato è molto più accurato rispetto alle formule trigonometriche classiche.

Questa query restituirà circa 166000 metri (ovvero 166 km), che rappresenta la distanza tra Palermo e Catania.

Creazione di una stored procedure

Per riutilizzare il calcolo all'interno di applicazioni o query automatizzate, possiamo creare una stored procedure parametrica.

Codice completo

CREATE PROCEDURE CalcolaDistanzaTraDuePunti
    @Lat1 FLOAT,
    @Lon1 FLOAT,
    @Lat2 FLOAT,
    @Lon2 FLOAT
AS
BEGIN
    DECLARE @Punto1 GEOGRAPHY = GEOGRAPHY::Point(@Lat1, @Lon1, 4326);
    DECLARE @Punto2 GEOGRAPHY = GEOGRAPHY::Point(@Lat2, @Lon2, 4326);

    SELECT 
        @Punto1.STDistance(@Punto2) AS DistanzaInMetri,
        ROUND(@Punto1.STDistance(@Punto2) / 1000.0, 2) AS DistanzaInKm;
END;

Esecuzione

EXEC CalcolaDistanzaTraDuePunti 
    @Lat1 = 38.1157, @Lon1 = 13.3615,
    @Lat2 = 37.5079, @Lon2 = 15.0830;

Espansione della procedura

La procedura può essere estesa per includere anche:

  • Nome dei punti come parametri

  • Salvataggio in una tabella di log

  • Calcolo di tempo di percorrenza stimato (con velocità media)

Uso pratico con una tabella

Supponiamo di avere una tabella con le posizioni dei negozi.

CREATE TABLE Negozi (
    Id INT PRIMARY KEY,
    Nome NVARCHAR(100),
    Posizione GEOGRAPHY
);

INSERT INTO Negozi (Id, Nome, Posizione)
VALUES (1, 'Negozio A', GEOGRAPHY::Point(38.12, 13.36, 4326));

Per trovare i negozi entro 10 km da una posizione:

DECLARE @PosUtente GEOGRAPHY = GEOGRAPHY::Point(38.1157, 13.3615, 4326);

SELECT Nome,
       Posizione.STDistance(@PosUtente) AS DistanzaMetri
FROM Negozi
WHERE Posizione.STDistance(@PosUtente) < 10000
ORDER BY DistanzaMetri;

Ottimizzazione con Spatial Index

Le query spaziali possono diventare lente su grandi volumi di dati. Per questo, è buona pratica creare un indice spaziale:

CREATE SPATIAL INDEX IX_Negozi_Posizione
ON Negozi(Posizione)
USING GEOGRAPHY_AUTO_GRID;

Con questo indice, SQL Server utilizza strutture ottimizzate per velocizzare i confronti geospaziali.

Integrazione con applicazioni moderne

I risultati delle query geografiche possono essere esportati in formato GeoJSON, integrati in API REST o visualizzati in mappe interattive tramite LeafletMapboxGoogle Maps. Questo consente di costruire interfacce utente moderne che rispondono dinamicamente alla posizione dell'utente.

Esempio di serializzazione in GeoJSON:

SELECT 'Feature' AS type,
       JSON_QUERY(
           CONCAT(
               '{"type":"Point","coordinates":[',
               CAST(Posizione.Long AS VARCHAR), ',',
               CAST(Posizione.Lat AS VARCHAR),
               ']}'
           )
       ) AS geometry
FROM Negozi

Ulteriori considerazioni

  • Precisione: Il tipo GEOGRAPHY considera la curvatura terrestre, offrendo maggiore precisione rispetto a soluzioni "manuali" basate su formule come Haversine.

  • Compatibilità: Puoi integrare questa logica in API RESTful o frontend, ad esempio mostrando i risultati su una mappa interattiva (Leaflet, Mapbox, Google Maps).

  • Estensioni: Puoi estendere la stored procedure per accettare più punti, usare TVP (Table-Valued Parameters) per batch di calcoli, o aggiungere logica per calcolare anche il tempo stimato in base alla distanza.

Esempi di casi d'uso reali

L'utilizzo delle funzionalità geospaziali in SQL Server trova applicazione in molti scenari reali. Di seguito alcuni esempi concreti:

1. Logistica e trasporti

Aziende di logistica possono calcolare le distanze tra magazzini, centri di distribuzione e destinazioni finali per ottimizzare le rotte di consegna. Le stored procedure geografiche possono essere utilizzate per pianificare percorsi efficienti, calcolare costi stimati e ridurre i tempi di viaggio.

2. Servizi di emergenza

Centrali operative di pronto intervento (ambulanza, vigili del fuoco, polizia) possono localizzare in tempo reale il punto di emergenza e trovare la stazione di partenza più vicina. Un sistema con stored procedure geospaziali può restituire rapidamente i tre punti di soccorso più vicini con stima delle distanze e dei tempi di arrivo.

3. Applicazioni mobili e geolocalizzazione

App come Uber, Deliveroo o Google Maps si basano su distanze dinamiche calcolate in tempo reale tra utenti, veicoli e punti di interesse. SQL Server con GEOGRAPHY può essere il backend di un sistema che mostra solo gli esercizi commerciali o i driver a meno di X km dall’utente.

4. Retail e marketing geolocalizzato

I grandi brand possono sfruttare le distanze geografiche per inviare promozioni mirate agli utenti che si trovano vicino ai punti vendita. Le query spaziali possono essere integrate con CRM e piattaforme di marketing automation per campagne personalizzate.

5. Analisi ambientale e pianificazione urbana

Organizzazioni pubbliche possono valutare l’impatto di nuove infrastrutture calcolando la distanza da aree protette, corsi d’acqua o zone residenziali. La pianificazione urbana può essere supportata da query spaziali per identificare aree raggiungibili entro una certa distanza da servizi essenziali (ospedali, scuole, ecc.).

Conclusione

Il calcolo della distanza tra punti geografici è una funzionalità fondamentale per molte applicazioni moderne. SQL Server, grazie al supporto nativo per il tipo GEOGRAPHY, permette di implementarla in modo semplice, preciso e performante. Creare una stored procedure dedicata consente di riutilizzare questa logica in diversi contesti e semplificare l'integrazione con altri sistemi.

Integrare queste soluzioni nel tuo database può migliorare notevolmente l'efficienza delle analisi geospaziali e fornire funzionalità avanzate agli utenti finali.