1

给定一点,我如何查询 SQL Server 以找到包含它的存储多边形?

我有一个包含美国所有 50 个州的多边形的数据库表。我需要一个查询,让我可以搜索距离该点 90 英里范围内的州。

这是我的三种状态的表结构和数据:

CREATE TABLE dbo.States (
State varchar(20) NOT NULL,
CoordinatorEmail varchar(255) NULL,
Borders geography(-1) NULL
);

INSERT INTO States (State, Borders) 
VALUES ('Alaska', (geography::STGeomFromText('POLYGON((-141.0205 70.0187,-141.7291 70.1292,-144.8163 70.4515,-148.4583 70.7471,-151.1609 70.7923,-152.6221 71.1470,-153.9954 71.1185,-154.8853 71.4307,-156.7529 71.5232,-157.9449 71.2796,-159.6313 71.2249,-161.8671 70.6363,-163.5809 70.0843,-165.2399 69.3028,-166.8768 69.1782,-168.0414 68.3344,-165.9155 67.6844,-164.6082 67.2933,-164.0149 66.7789,-165.7507 66.5810,-167.5745 66.2867,-168.9862 66.0269,-168.9478 65.4970,-167.4756 65.0420,-167.0142 64.3922,-165.7343 64.0554,-163.2294 64.0193,-162.1143 63.9615,-163.6029 63.6877,-165.3717 63.4530,-166.3715 62.4133,-166.9867 61.6534,-166.4429 60.8556,-167.8381 60.5357,-167.7118 59.5482,-165.8002 59.4115,-164.5972 59.3696,-162.8558 59.1168,-162.5427 58.1185,-160.6421 58.1359,-159.5050 58.0285,-158.8953 57.6336,-159.9060 56.9090,-160.6531 56.3926,-161.8835 56.2342,-162.9822 55.7240,-164.3994 55.2478,-165.3168 54.7753,-167.1075 54.1463,-168.5852 53.5632,-169.9146 53.1402,-169.5959 52.5964,-168.2227 52.9089,-162.7734 54.2139,-159.1452 54.6786,-155.4634 55.6567,-152.1400 57.3510,-150.8203 59.2209,-147.4461 59.7695,-145.9850 60.3521,-144.1544 59.8917,-141.6811 59.8172,-140.5124 59.5225,-138.8548 59.0292,-136.8526 57.9032,-136.0725 56.9157,-134.9794 56.1555,-134.0057 55.3237,-133.6418 54.6341,-130.6261 54.7135,-129.9930 55.2869,-130.0108 55.9869,-130.1083 56.1057,-131.5887 56.6086,-132.8755 57.8404,-133.8423 58.7276,-134.9121 59.3108,-135.4724 59.8020,-136.3445 59.6039,-136.8251 59.1619,-137.6079 59.2441,-139.2119 60.0902,-139.0938 60.3575,-140.0056 60.1866,-140.9999 60.3059,-141.0205 70.0187,-141.0205 70.0187))', 4326)));


INSERT INTO States (State, Borders) 
VALUES ('Alabama', (geography::STGeomFromText('POLYGON((-88.1955 35.0041,-85.6068 34.9918,-85.1756 32.8404,-84.8927 32.2593,-85.0342 32.1535,-85.1358 31.7947,-85.0438 31.5200,-85.0836 31.3384,-85.1070 31.2093,-84.9944 31.0023,-87.6009 30.9953,-87.5926 30.9423,-87.6256 30.8539,-87.4072 30.6745,-87.3688 30.4404,-87.5240 30.1463,-88.3864 30.1546,-88.4743 31.8939,-88.1021 34.8938,-88.1721 34.9479,-88.1461 34.9107,-88.1955 35.0041))', 4326)));


INSERT INTO States (State, Borders) 
VALUES ('Arkansas', (geography::STGeomFromText('POLYGON((-94.0416 33.0225,-91.2057 33.0075,-91.1989 33.1180,-91.1041 33.1824,-91.1343 33.3053,-91.1646 33.4211,-91.2263 33.4337,-91.2524 33.5403,-91.1797 33.6112,-91.2524 33.6855,-91.1261 33.6946,-91.1412 33.7883,-91.0451 33.7700,-91.0341 33.8328,-91.0863 33.9399,-90.9256 34.0208,-90.9036 34.0856,-90.9586 34.1345,-90.9132 34.1675,-90.8501 34.1380,-90.9325 34.2311,-90.6935 34.3446,-90.5603 34.4409,-90.5548 34.5348,-90.5768 34.5959,-90.5301 34.7213,-90.5328 34.7574,-90.4546 34.8780,-90.3529 34.8454,-90.2911 34.8690,-90.3104 35.0255,-90.2843 35.1154,-90.1772 35.1323,-90.1112 35.1985,-90.1524 35.2826,-90.1332 35.4383,-90.0206 35.5579,-89.9780 35.6740,-89.9547 35.7287,-89.6594 35.9169,-89.6883 35.9658,-89.7130 36.0013,-90.3735 35.9958,-90.2664 36.1268,-90.0934 36.2875,-90.0742 36.3892,-90.1511 36.4180,-90.1566 36.4997,-94.6198 36.4986,-94.4412 35.3801,-94.4893 33.6318,-94.4522 33.6421,-94.4000 33.5597,-94.2462 33.5883,-94.1885 33.5872,-94.0375 33.5345,-94.0430 33.4314,-94.0430 33.0213,-94.0416 33.0225))', 4326)));

我一直在尝试以下查询,以确保我可以获得该点的状态(还不必担心 90 英里的半径),但我还没有弄清楚这部分。

DECLARE @LittleRock geography;
SET @LittleRock = geography::Point(34.742000, -92.276543, 4326);

Select State from States 
where States.Borders.STIntersects(@LittleRock) = 1;

SELECT State from States 
where States.Borders.STContains(@LittleRock) = 1;

既不STIntersets()也不STContains()返回任何东西。想法?

4

1 回答 1

1

当我在本地实例上运行您的代码时,出现以下错误(缩写):

此操作无法完成,因为实例无效。使用 MakeValid 将实例转换为有效实例。

接下来,我做了机器人告诉我要做的事情:

UPDATE dbo.States
SET Borders = Borders.MakeValid();

一旦完成,我就能够确定小石城确实在阿肯色州,同时STIntersects()STContains()。因此,至少在您的一个地理实例中存在格式错误。

编辑

鉴于 OPs 的完整数据集,它与某些状态存在另一个问题。具体来说,21 个州似乎存在环方向问题。对于地理多边形,指定顶点的顺序很重要。我不记得顺时针还是逆时针方向是正确的。但我确实记得我使用的启发式方法。如果多边形的包络角大于 90°,我可能弄错了。幸运的是,这也很容易纠正。

UPDATE s
SET s.Borders = s.Borders.ReorientObject()
FROM dbo.States AS s
WHERE s.Borders.EnvelopeAngle() > 90

使用原始数据集,您的 Little Rock 查询返回 22 个状态。通过上面的更新运行,它只返回阿肯色州。

于 2018-03-29T19:02:31.317 回答