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).