sql >> Base de Datos >  >> RDS >> Sqlserver

Cálculo de distancia con una enorme base de datos de SQL Server

Podrías hacer algo peor que mirar la GEOGRAPHY tipo de datos, por ejemplo:

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 toma la latitud y la longitud, así como un SRID (Número de identificación de referencia especial). En este caso, el SRID es 4326, que es la latitud y longitud estándar. Como ya tiene la latitud y la longitud, puede simplemente ALTER TABLE para agregar la columna de geografía, luego UPDATE para llenarlo.

He mostrado dos formas de sacar los datos de la tabla, sin embargo, no puede crear una vista indexada con esto (las vistas indexadas no pueden tener uniones automáticas). Sin embargo, podría crear una tabla secundaria que sea efectivamente un caché, que se complete en función de lo anterior. Luego, solo tiene que preocuparse por mantenerlo (se puede hacer a través de disparadores o algún otro proceso).

Tenga en cuenta que la unión cruzada le dará 250 000 000 000 filas, pero la búsqueda es simple ya que solo necesita mirar una de las columnas de lugares (es decir, SELECT * FROM table WHERE Place1 = 'Sheffield' AND distance < 100 , el segundo le dará significativamente menos filas, pero la consulta debe considerar tanto la columna Place1 como Place2).