20

Estoy usando los tipos de datos espaciales de SQL Server 2008. Tengo una tabla con todos los estados (como polígonos) como tipo de datos GEOMETRÍA. Ahora quiero verificar si las coordenadas de un punto (latitudes, longitudes) como el tipo de datos GEOGRAPHY, están dentro de ese estado o no.SQL Server 2008 Spatial: busque un punto en el polígono

No pude encontrar ningún ejemplo utilizando los nuevos tipos de datos espaciales. Actualmente, tengo una solución que se implementó hace muchos años, pero tiene algunos inconvenientes.

Tengo SQL Server 2008 y 2012. Si la nueva versión tiene algunas mejoras, puedo empezar a trabajar en ella también.

Gracias.

ACTUALIZACIÓN 1:

añado un ejemplo de código para un poco más de claridad.

declare @s geometry --GeomCol is of this type too. 
declare @z geography --GeogCol is of this type too. 

select @s = GeomCol 
from AllStates 
where STATE_ABBR = 'NY' 

select @z = GeogCol 
from AllZipCodes 
where ZipCode = 10101 
+0

su rendimiento es pobre si tiene registros enormes en la base de datos, he intentado esta consulta sobre 1600000 registros y tardó media de 2 minutos para completar. –

Respuesta

26

creo que los STIntersects método de la geografía() lo hará lo que quiere:

DECLARE @g geography; 
DECLARE @h geography; 
SET @g = geography::STGeomFromText('POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))', 4326); 
SET @h = geography::Point(47.653, -122.358, 4326) 

SELECT @g.STIntersects(@h) 
+0

Gracias. Pero mi polígono, Estados, está en un tipo de datos GEOMETRÍA. ¿Debo cambiarlo primero a una variable de GEOGRAFÍA? – Farhan

+0

Ah ... ¡Ups! Me perdí esa parte de eso. ¿Hay alguna razón por la cual sus estados (datos geográficos) se almacenan como datos geométricos? –

+0

En realidad, no hay ninguna razón para eso. Cuando estaba repasando algunos tutoriales, asumí que el tipo de datos GEOGRAPHY es para coordenadas/puntos y GEOMETRY es para regiones/polígonos. – Farhan

2

Si no puede cambiar el tipo de datos para los polígonos almacenados a GEOGRAPHY entonces usted puede convertir la latitud de entrada y longitud a GEOMETRY y use STContains o STIntersects contra el valor convertido.

DECLARE @PointGeography GEOGRAPHY = geography::Point(43.365267, -80.971974, 4326) 
DECLARE @PointGeometry GEOMETRY = geometry::STGeomFromWKB(@PointGeography.STAsBinary(), 4326); 

SELECT @PolygonGeometry.STContains(@PointGeometry); 

en sentido contrario - tratar de convertir a los polígonos GEOMETRY a GEOGRPAHY - es propenso a errores y propensos a fallar de mi experiencia.

Y tenga en cuenta que si intenta crear el punto de GEOMETRY directamente a partir de los valores de latitud y longitud, entonces el STContains (o STIntersects) no funciona (es decir, no dará un partido cuando deberían hacerlo).

0
declare @g geometry 
set @g=geometry::STGeomFromText('POLYGON((-33.229869 -70.891988, -33.251124 -70.476616, -33.703094 -70.508045, -33.693931 -70.891052,-33.229869 -70.891988))',0) 

DECLARE @h geometry; 

SET @h = geometry::STGeomFromText('POINT(-33.3906300 -70.5725020)', 0); 
SELECT @g.STContains(@h); 
0
  1. No deberías estar mezclando Geometría y Geografía. La geometría es para PLANOS PLANOS, la Geografía es para ESFÉRICOS (como la Tierra).
  2. "debería" conciliar los SRID para hacer frente a esto. Cada SRID (por ejemplo, 2913 = NZG2000) describe una relación de transformación. Cada SRID se puede usar para asignar a/desde una esfera uniforme, que es cómo se pasa de uno a otro.
  3. Hasta que llegue a un "mismo" SRID en ambos valores, muchos para las funciones .STxXX devolverán NULL (puede tener el valor predeterminado 0 en ambos casos)
  4. Si no son lo mismo pero fingen serlo, es posible que tenga errores en los casos extremos.
  5. Si gasta un poco de tiempo "precalcificado", puede determinar los puntos superior/izquierdo e inferior/derecho para las rectas de delimitación involucradas (y almacenarlas), y usar esos valores en índices para limitar los registros a verificar. A menos que AT/L < BB/R y AB/R> BT/L no pueden superponerse, lo que significa un simple 4 y numéricos cheque en su DONDE limitará su STWithin comprueba

He aquí un ejemplo que utilicé en SRID 2193.Todos los caminos dentro de un radio de 3 kilometros de un punto dado, y dentro de una zona escolar específica

DECLARE @g geometry 

SELECT @g = GEO2193 FROM dbo.schoolzones WHERE schoolID = 319 

SELECT DD.full_road_name, MIN(convert(int, dd.address_number)), MAX(convert(int, dd.address_number)) 
FROM (

select A.* from dbo.[street-address] A 

WHERE (((A.Shape_X - 1566027.50505) * (A.Shape_X - 1566027.50505)) + ((A.Shape_Y - 5181211.81675) * (A.Shape_Y - 5181211.81675))) < 9250000 

and a.shape_y > 5181076.1943481788 

and a.shape_y < 5185097.2169968253 

and a.shape_x < 1568020.2202472512 

and a.shape_x > 1562740.328937705 

and a.geo2193.STWithin(@g) = 1 
) DD 
GROUP BY DD.full_road_name 
ORDER BY DD.full_road_name 
Cuestiones relacionadas