Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Calcolo della distanza con un enorme database di SQL Server

Potresti fare di peggio che guardare la GEOGRAPHY tipo di dati, ad esempio:

CREATE TABLE Places
(
    SeqID       INT IDENTITY(1,1),
    Place       NVARCHAR(20),
    Location    GEOGRAPHY
)
GO
INSERT INTO Places (Place, Location) VALUES ('Coventry', geography::Point(52.4167, -1.55, 4326))
INSERT INTO Places (Place, Location) VALUES ('Sheffield', geography::Point(53.3667, -1.5, 4326))
INSERT INTO Places (Place, Location) VALUES ('Penzance', geography::Point(50.1214, -5.5347, 4326))
INSERT INTO Places (Place, Location) VALUES ('Brentwood', geography::Point(52.6208, 0.3033, 4326))
INSERT INTO Places (Place, Location) VALUES ('Inverness', geography::Point(57.4760, -4.2254, 4326))
GO
SELECT p1.Place, p2.place, p1.location.STDistance(p2.location) / 1000 AS DistanceInKilometres
    FROM Places p1
    CROSS JOIN Places p2
GO  
SELECT p1.Place, p2.place, p1.location.STDistance(p2.location) / 1000 AS DistanceInKilometres
    FROM Places p1
        INNER JOIN Places p2 ON p1.SeqID > p2.SeqID
GO  

geography::Point prende la latitudine e la longitudine, nonché un SRID (numero ID di riferimento speciale). In questo caso, lo SRID è 4326 che è latitudine e longitudine standard. Dato che hai già latitudine e longitudine, puoi semplicemente ALTER TABLE per aggiungere la colonna geografica, quindi UPDATE per popolarlo.

Ho mostrato due modi per estrarre i dati dalla tabella, tuttavia non è possibile creare una vista indicizzata con questa (le viste indicizzate non possono avere collegamenti automatici). Potresti però creare una tabella secondaria che sia effettivamente una cache, che viene popolata in base a quanto sopra. Quindi devi solo preoccuparti di mantenerlo (potrebbe essere fatto tramite trigger o qualche altro processo).

Nota che il cross join ti darà 250.000.000.000 di righe, ma la ricerca è semplice in quanto devi solo guardare una delle colonne dei luoghi (ad esempio, SELECT * FROM table WHERE Place1 = 'Sheffield' AND distance < 100 , il secondo ti darà molte meno righe, ma la query deve quindi considerare sia la colonna Place1 che Place2).