【问题标题】:Postgres returning in-correct results with distance join queriesPostgres 使用距离连接查询返回不正确的结果
【发布时间】:2017-05-19 05:14:03
【问题描述】:

我创建了一个表格,其中包含位置及其在 postgres 中以(纬度、经度(度)表示的空间坐标。我用于相同的命令是:

我在 postgres 中插入空间坐标为(经度,纬度)

我创建了一个表格,其中包含位置及其在 postgres 中以(纬度、经度(度)表示的空间坐标。我用于相同的命令是:

CREATE TABLE spatialTest(
  name character varying(100),
  the_geo geography
);
\copy spatialTest(name,the_geo) FROM 'testSpatial.csv' DELIMITERS E'\t' CSV;

testSpatial.csv 包含以下值:

A   SRID=4326;POLYGON((0.178773 -127.681841,0.178711 -127.681962,0.179125 -127.682083,0.179176 -127.682006,0.179153 -127.681986,0.179143 -127.681962,0.179147 -127.681935,0.179166 -127.681913,0.179195 -127.681897,0.179244 -127.681886,0.179284 -127.681887,0.179336 -127.681904,0.179464 -127.681757,0.179489 -127.681736,0.179429 -127.681680,0.179370 -127.681516,0.179221 -127.681331,0.179184 -127.681185,0.179051 -127.681264,0.178822 -127.681499,0.178761 -127.681698,0.178796 -127.681703,0.178839 -127.681721,0.178857 -127.681736,0.178861 -127.681740,0.178871 -127.681756,0.178873 -127.681782,0.178859 -127.681809,0.178843 -127.681825,0.178812 -127.681839,0.178773 -127.681841))
B   SRID=4326;POINT(0.628912 -127.700922)

现在我想找到彼此相距 50 公里以内的所有空间位置。为此,我使用了以下命令:

select s1.name, s2.name  from spatialTest s1, 
     spatialTest s2  where ST_DWithin(s1.the_geo, s2.the_geo, 50000);

然而,令我惊讶的是,我发现虽然 A 和 B 之间的距离大于 50 公里(准确地说是 50.0995 公里。使用 Chris Veness 的大地测量公式找到(计算点和线之间的距离)纬度和经度段)),但它们由 postgres 作为结果返回。有人可以帮我弄清楚我哪里出错了。

我正在使用 PostgreSQL 9.6devel 和 Postgis 版本,我使用的是:POSTGIS="2.2.1 r14555"

【问题讨论】:

  • 你在 Postgres “Bugs” 邮件列表上得到了答案:“我认为你需要在 Postgis 邮件列表上询问这个问题,而不是在这里” - 确实你做吧?为什么不使用适当的 Postgres 版本?
  • 您的代码和示例数据由我返回错误:ERROR: parse error - invalid geometry HINT: "SRID=4326;POINT(0.628912,-" <-- parse error at position 26 within geometry。请添加正确的数据和代码示例
  • “postgres 中以(纬度,经度(度))表示的空间坐标” 我认为您需要按经度、纬度顺序传递参数。也就是说,第一个参数是经度,而不是纬度。这可能是您的全部或部分问题吗?
  • 您应该将其发布在 PostGIS 邮件列表中,而不是 Postgres 邮件列表中
  • 您的坐标是无效的经纬度坐标。也许它们的顺序相反? COPY 返回此警告:NOTICE: Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY

标签: postgresql postgis


【解决方案1】:

正如其他人所说,你正在加载这个..

NOTICE:  Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY
CONTEXT:  COPY spatialtest, line 2, column the_geo: "SRID=4326;POINT(0.628912 -127.700922)"

很可能,您正在尝试加载 (lat,long),而 PostgreSQL 期望加载 (long,lat)。但是,我们可以解决您输入列的顺序问题。我们所要做的就是,

  1. 创建一个临时表asgeometry`。

    CREATE TEMP TABLE foo(name text, the_geo geometry);
    
  2. 切断在导入时丢失 SRID 的 SRID 位 (EKWT)。

    sed -i -e's/SRID=4326;//' ./foo.csv
    
  3. 加载输入。

    \copy foo(name,the_geo) FROM 'foo.csv' DELIMITERS E'\t' CSV;
    
  4. 重新排列点。
  5. 复制到主表中。

    INSERT INTO spatialTest(name, the_geo)
    SELECT
      name,
      ST_Union(
        ST_SetSRID(
          ST_MakePoint(st_y(geom), st_x(geom))
        ,4326)
      )::geography
    FROM foo
    CROSS JOIN ST_DumpPoints(foo.the_geo) AS t
    GROUP BY name
    ORDER BY name;
    

附带说明:不要使用 varchar 作为名称。只需将其保留为TEXT。除非您有充分的理由施加字符限制。

然后跑你的距离..

SELECT ST_Distance(
  (SELECT the_geo FROM spatialtest WHERE name='A'), (SELECT the_geo FROM spatialtest WHERE name='B')
);
  st_distance   
----------------
 49740.52214618
(1 row)

【讨论】:

  • 我尝试了 (long, lat) 但仍然遇到同样的错误
  • 同样的错误是什么意思,我刚刚得到了 49.7 KM 的 st_distance?你想要什么?
猜你喜欢
  • 2011-10-14
  • 2017-05-09
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多