获取半径中的地理位置

时间:2018-08-23 14:13:03

标签: sql postgresql postgis

我的桌子看起来像:

CREATE TABLE public.places
    (
        id bigint DEFAULT nextval('places_id_seq'::regclass) PRIMARY KEY NOT NULL,
        lon numeric(18,13) DEFAULT NULL::numeric,
        lat numeric(18,13) DEFAULT NULL::numeric,
        location geography(Point,4326)
    );
    CREATE INDEX places_ll ON public.places (lon, lat);
    CREATE INDEX places_location_ix ON public.places (location);
    INSERT INTO public.places (id, lon, lat, location) VALUES (1, 14.4783371228873, 46.0299536240291, '0101000020E610000003CD3585D50347400287769AE8F42C40');

现在我无法通过查询找到附近的位置

SELECT ST_Distance(Geography(ST_MakePoint(14.47859, 46.02998166)), location) as dist, lon, lat, location FROM places
WHERE ST_DWithin(Geography(ST_MakePoint(14.47859, 46.02998166)), Geography(location), 50) ORDER BY dist LIMIT 1;

我得到零结果。然后我尝试查询:

SELECT ST_Distance(Geography(ST_MakePoint(14.47859, 46.02998166)), ST_MakePoint(lon,lat)) as dist, lon, lat, location FROM places
WHERE ST_DWithin(Geography(ST_MakePoint(14.47859, 46.02998166)), Geography(ST_MakePoint(lon,lat)), 50) ORDER BY dist LIMIT 1;

我得到一个结果:

14.4783371228873    46.0299536240291    0101000020E610000003CD3585D50347400287769AE8F42C40

问题是第二个查询返回结果,但是要慢得多,而第一个查询不返回结果,但是非常快(索引搜索)。当然,我想要两者的混合。毫不奇怪,我想要结果并且要尽可能快。

2 个答案:

答案 0 :(得分:1)

您的坐标对可能已反转。请记住,ST_MakePoint期望 x,y ,而不是 y,x 。您在也门的某个地方-POINT(46.0299536240291 14.4783371228873)

enter image description here

或者在斯洛文尼亚-POINT(14.4783371228873 46.0299536240291)

enter image description here

“地理”列或ST_MakePoint处的坐标对都被反转。

此外,地理类型列中的地理功能(在查询中用作Geography(location))是多余的。似乎您还试图将 x,y 存储在单独的列中,然后在geography列中插入相同的值。如果可以的话,请除去 x,y 列,因为它们也是多余的... 地理位置就足够了。

如果x,y为46.02998166,14.47859,请尝试以下操作:

SELECT 
  ST_Distance(Geography(ST_MakePoint(46.02998166,14.47859)), location) AS dist, 
  lon, lat, ST_AsText(location) 
FROM places
WHERE 
  ST_DWithin(Geography(ST_MakePoint(46.02998166,14.47859)), 
  location, 50) ORDER BY dist LIMIT 1;

    dist     |       lon        |       lat        |                st_astext                 
-------------+------------------+------------------+------------------------------------------
 28.14204157 | 14.4783371228873 | 46.0299536240291 | POINT(46.0299536240291 14.4783371228873)

答案 1 :(得分:0)

location和您创建的点经纬度倒置。可以理解的是,这两个查询花费的时间不同(使用索引来过滤所有行而不是计算/排序精确的距离)

select st_astext('0101000020E610000003CD3585D50347400287769AE8F42C40');
                st_astext
------------------------------------------
 POINT(46.0299536240291 14.4783371228873)