20

Tôi đang sử dụng các kiểu dữ liệu không gian SQL Server 2008. Tôi có một bảng với tất cả các quốc gia (như đa giác) như kiểu dữ liệu GEOMETRY. Bây giờ tôi muốn kiểm tra xem các tọa độ của một điểm (vĩ độ, kinh độ) có phải là kiểu dữ liệu GEOGRAPHY, nằm trong trạng thái đó hay không.SQL Server 2008 Spatial: tìm một điểm trong đa giác

Tôi không thể tìm thấy bất kỳ ví dụ nào bằng cách sử dụng các loại dữ liệu không gian mới. Hiện tại, tôi có một cách giải quyết được thực hiện nhiều năm trước, nhưng nó có một số nhược điểm.

Tôi đã SQL Server 2008 và 2012. Nếu phiên bản mới có một số cải tiến, tôi cũng có thể bắt đầu làm việc trong đó.

Cảm ơn.

CẬP NHẬT 1:

Tôi đang thêm mẫu mã để rõ ràng hơn một chút.

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

Hiệu suất của nó là kém nếu bạn có hồ sơ lớn trong cơ sở dữ liệu, tôi đã thử truy vấn trên 1600000 bản ghi và mất khoảng 2 phút hoàn thành. –

Trả lời

26

Tôi nghĩ rằng STIntersects phương pháp địa lý() sẽ làm những gì bạn muốn:

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

Cảm ơn. Nhưng đa giác của tôi, Hoa, nằm trong kiểu dữ liệu GEOMETRY. Tôi có nên thay đổi nó thành biến GEOGRAPHY trước không? – Farhan

+0

Ah ... Rất tiếc. Tôi đã bỏ lỡ phần đó. Có lý do nào mà các tiểu bang của bạn (dữ liệu địa lý) được lưu trữ dưới dạng dữ liệu hình học? –

+0

Thực ra, không có lý do gì cho điều đó. Như tôi đã đi qua một số hướng dẫn, tôi chỉ giả định rằng kiểu dữ liệu GEOGRAPHY là cho tọa độ/điểm và GEOMETRY là cho các khu vực/đa giác. – Farhan

2

Nếu bạn không thể thay đổi dữ liệu kiểu cho các đa giác được lưu trữ để GEOGRAPHY sau đó bạn có thể chuyển đổi các vĩ độ đầu vào và kinh độ để GEOMETRY và sử dụng STContains hoặc STIntersects so với giá trị được chuyển đổi.

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

SELECT @PolygonGeometry.STContains(@PointGeometry); 

Đi theo hướng ngược lại - cố gắng để chuyển đổi GEOMETRY đa giác để GEOGRPAHY - là dễ bị lỗi và khả năng thất bại từ kinh nghiệm của tôi. Và hãy lưu ý rằng nếu bạn cố gắng tạo ra các điểm GEOMETRY trực tiếp từ các giá trị vĩ độ và kinh độ thì STContains (hoặc STIntersects) sẽ không hoạt động (tức là sẽ không khớp khi cần). Lưu ý:

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. Bạn không nên trộn hình học và địa lý. Hình học là dành cho PLANAT FLAT, Địa lý dành cho SPHEROIDS (như Earth).
  2. Bạn "nên" điều chỉnh SRID để giải quyết vấn đề này. Mỗi SRID (ví dụ: 2913 = NZG2000) mô tả mối quan hệ chuyển đổi. Mỗi SRID có thể được sử dụng để ánh xạ tới/từ một quả cầu đồng nhất, đó là cách bạn nhận được từ một đến hình cầu khác.
  3. Cho đến khi bạn nhận được SRID "giống nhau" trên cả hai giá trị, nhiều hàm cho hàm .STxXX sẽ trả về NULL (bạn có thể có 0 mặc định trong cả hai trường hợp)
  4. Nếu chúng không giống nhau nhưng bạn giả vờ như vậy, bạn có thể có lỗi trên các trường hợp cạnh.
  5. Nếu bạn dành thời gian "precalc", bạn có thể xác định các điểm trên cùng/trái và dưới/phải cho các đường bao quanh (và lưu chúng) và sử dụng các giá trị đó trong các chỉ mục để giới hạn các bản ghi để kiểm tra. Trừ khi AT/L < BB/R và AB/R> BT/L họ không thể chồng lên nhau, có nghĩa là một kiểm tra đơn giản 4 VÀ số trong ĐÂU của bạn sẽ hạn chế STWithin bạn kiểm tra

Dưới đây là một ví dụ tôi sử dụng trong SRID 2193.Tất cả các con đường trong bán kính 3km của một điểm nhất định và bên trong một khu vực cụ thể là

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 
Các vấn đề liên quan