获取半径范围内的地理位置

问题描述 投票:1回答:2

我有桌子看起来像:

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

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

sql postgresql postgis
2个回答
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存储在单独的列中,然后在地理列中插入相同的值。如果可以的话,摆脱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)

0
投票

location和你创造的点有lat-long倒置。可以理解的是,这两个查询需要不同的时间(使用索引来过滤掉所有行而不是计算/排序确切的距离)

select st_astext('0101000020E610000003CD3585D50347400287769AE8F42C40');
                st_astext
------------------------------------------
 POINT(46.0299536240291 14.4783371228873)
© www.soinside.com 2019 - 2024. All rights reserved.