Geography data type vs. Geometry data type in SQL

2020-07-25 12:25发布

问题:

Environment: SQL Server 2012 I'm using an online tool, the only one I could find so far, to plot polygons and points on the earth. http://www.birdtheme.org/useful/googletool.html I have two tables. One stores "areas" as polygons and the other table stores points amongst other things irrelevant to my question. For simplicity, I'll just reduce my scenario to sql variables.

In the query below, I'm using the geography data type for well known points of interest. I drew a polygon around Robben Island, a point in Robben Island and a point in Alcatraz.

DECLARE @robben_island geography = ('POLYGON((18.351803 -33.788421,18.382788 -33.787494,18.386736 -33.820515,18.354464 -33.822369,18.351803 -33.788421))')
DECLARE @point_in_robben_island geography= ('POINT(18.369226 -33.80554)')
DECLARE @point_in_alcatraz geography= ('POINT(-122.423401 37.827006)')

SELECT @robben_island.STContains(@point_in_robben_island)   --returns 'False', but it's not what I expected
SELECT @robben_island.STContains(@point_in_alcatraz)        --returns 'True', but it's not what I expected

This query above, if I understand it correctly, tells me that my @point_in_robben_island is not contained in @robben_island, rather my @point_in_alcatraz exists in @robben_island which as we all know, is not true.

Now when I change the data types from geography to geometry, everything works fine, but I'm afraid that if I continue using the geometry data type I might come across a few gotchas. I'm just wondering if I won't be negatively affected by fact that geometry doesn't quite account for earth's curvature. touch wood.

DECLARE @robben_island geometry = ('POLYGON((18.351803 -33.788421,18.382788 -33.787494,18.386736 -33.820515,18.354464 -33.822369,18.351803 -33.788421))')
DECLARE @point_in_robben_island geometry= ('POINT(18.369226 -33.80554)')
DECLARE @point_in_alcatraz geometry= ('POINT(-122.423401 37.827006)')

SELECT @robben_island.STContains(@point_in_robben_island)   --returns 'True' as it should
SELECT @robben_island.STContains(@point_in_alcatraz)        --returns 'False' as it should

Now my question is, why does the geography data type return unexpected results while geometry works as expected? Thank you very much.

回答1:

The geography type is a little bit more restrictive than geometry. It can't cross different hemispheres and the outer ring must be drawn counter-clockwise.

Unfortunately (some find this a good thing), SQL Server 2012 no longer throws an error when you create the invalid geography. You need to invert the order of the points in the Roben Island geometry, like:

DECLARE @robben_island geography = ('POLYGON((18.351803 -33.788421, 18.354464 -33.822369,18.386736 -33.820515, 18.382788 -33.787494, 18.351803 -33.788421))')
DECLARE @point_in_robben_island geography= ('POINT(18.369226 -33.80554)')
DECLARE @point_in_alcatraz geography= ('POINT(-122.423401 37.827006)')

SELECT @robben_island.STContains(@point_in_robben_island)   --returns 'True'
SELECT @robben_island.STContains(@point_in_alcatraz)        --returns 'False'