Postdis中的ST_Distance和'as'

时间:2011-02-02 18:09:38

标签: syntax distance postgis

我已经编写了这个查询并且它有效,虽然它有点慢:

SELECT name,
(ST_Distance( ST_Transform( way,900913 ),ST_Transform( ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913 )))
FROM ga_osm_latlong_polygon 
WHERE 
( (ST_Distance( ST_Transform( way,900913 ),ST_Transform( ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913 )))
<= 1000 ) 
ORDER BY
(ST_Distance( ST_Transform( way,900913 ),ST_Transform( ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913 ))),
name

我正试图以更优雅的方式重写它,使用'as':

SELECT name,
(ST_Distance( ST_Transform( way,900913 ),ST_Transform( ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913 ))) AS d
FROM ga_osm_latlong_polygon 
WHERE ( d <= 1000 ) 
ORDER BY d, name

不幸的是,我得到: 错误:列“d”不存在

我对这里的错误有所了解吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

Hallo Mulone

关于你的别名问题,路德是对的。

关于查询缓慢有两个原因。

首先,你正在改变每一点,这需要时间

第二个也许更重要的是,你应该使用ST_Dwithin和空间索引,而不是在where子句中使用distance。

ST_Dwithin使用空间索引对很多计算进行排序。

但是,将数据投射到那些计算中会给出非常不准确的答案。为什么不使用地理功能呢。

尝试:

SELECT d, name
(
  SELECT ST_Distance(a.way,b.geom) as d, a.name from 
      (SELECT way::geography, name from ga_osm_latlong_polygon) a, 
      (SELECT 'POINT(-6.2222 53.307)'::geography as geom) b 
  where ST_DWithin(a.way, b.geom, 1000)
) c
order by d, name;

但我想我会更简单地写它:

  SELECT ST_Distance(a.way,b.geom) as d, a.name from 
      (SELECT way::geography, name from ga_osm_latlong_polygon) a, 
      (SELECT 'POINT(-6.2222 53.307)'::geography as geom) b 
  where ST_DWithin(a.way, b.geom, 1000)
order by ST_Distance(a.way,b.geom), name;

但是第一个版本可能会更快,因为避免ST_Distance运行两次。

但是为了让这个工作顺利,你需要空间索引 现在,当我写它时,我意识到对地理的投射可能是指数的一个显示。如果是这样,我建议您改为创建一个地理专栏,并在其上建立一个合适的索引。工作指数在这里有所不同,如夜晚和白天。

<强>更新 或者您可以直接使用地理类型创建索引。我没有尝试,但可能值得尝试:像这样:

Create index idx_polygon_geog
on ga_osm_latlong_polygon
using gist(way::geography);

HTH

尼克拉斯

答案 1 :(得分:0)

在WHERE子句中看不到列别名。您可以像这样重写查询:

SELECT * FROM
 (
  SELECT name,
          (ST_Distance( 
            ST_Transform( way,900913 ),
            ST_Transform( ST_GeomFromText('POINT (-6.2222  53.307)',4326),900913 ))) 
      AS d
  FROM  ga_osm_latlong_polygon
 ) 

AS tmp    
WHERE ( d <= 1000 ) 
ORDER BY d, name

另外,我不确定PostGIS是否可以利用ST_Distance()谓词中的空间索引。根据目前的文档:

http://postgis.refractions.net/documentation/manual-1.5/ch04.html#id2638955

ST_Distance()包括从版本1.3开始的隐式边界框检查(可以对索引完成),但是在ST_Transform之后检查way,这意味着查询必须扫描所有行。可以尝试重写查询,将way保留在原始SRID中吗?像ST_Distance(way,ST_Transform(...,<srid of way>))一样?