【问题标题】:POSTGIS Get nearest locations queryPOSTGIS 获取最近的位置查询
【发布时间】:2020-11-06 01:04:57
【问题描述】:

我正在尝试获取位于用户附近 100 公里范围内的所有优惠。用户分享位置,我在 Offers 表中查询 - id、name、text、addressId(addressId 是外键)

地址表 - id、地址、位置。

Select Offers.id, Address.id 
from Offers, Address 
where 
  ST_Distance(
    ST_Transform( [12.9406589,77.6185572] ]::Geometry, 3857),
    ST_Transform( Address.location::Geometry, 3857) < 100 
  and Address.id = Offers.addressId

当我运行上面的查询时,它抛出了一个语法错误:

“]”附近的 Postgres 语法错误

我应该如何给出坐标?

【问题讨论】:

    标签: sql postgresql postgis


    【解决方案1】:

    您是否尝试过结合ST_MakePoint and ST_SetSRID 来创建您的观点?

    SELECT Offers.id, Address.id 
    FROM Offers, Address 
    WHERE 
     ST_Distance(
       ST_SetSRID(ST_MakePoint(12.9406589,77.6185572),3857),
       ST_Transform( Address.location::Geometry, 3857)) < 100 AND 
    Address.id = Offers.addressId
    

    注意:函数ST_MakePoint 期望参数为longitude,latitude,而不是相反。

    另见此相关answer

    【讨论】:

    • 感谢 Jim 的建议,但现在我得到了 - 错误:关系“offers”不存在第 2 行:FROM Offers,地址 ^ SQL 状态:42P01 字符:36
    • @regShank 表offers 存在吗?
    • Sql 查询我从 pgadmin 获得的表 - CREATE TABLE public."Offers" (id integer NOT NULL DEFAULT nextval('"Offers_offerId_seq"'::regclass), CONSTRAINT "Offers_pkey" PRIMARY KEY (id), CONSTRAINT "Offers_addressId_fkey" FOREIGN KEY ("addressId") REFERENCES public."Address" (id) MATCH SIMPLE ON DELETE RESTRICT, CONSTRAINT "Offers_vendorId_fkey" FOREIGN KEY ("vendorId") REFERENCES public."Vendors" (id) MATCH SIMPLE ON UPDATE RESTRICT ON DELETE RESTRICT )
    • @regShank 错误信息其实很清楚。在您的会话中找不到表 offers。可能是对多个数据库有多个会话并且您正在混合连接吗?您还可以将模式显式添加到表名中,例如public.offers.
    • 您可以将表名更改为不需要使用ALTER TABLE public."Offers" RENAME TO offers; 引用的名称,只要您不破坏任何依赖关系,其他人希望该表实际命名为Offers。你不需要引用public - 它已经是小写了。 PostgreSQL folds unquoted identifiers to lowercase.
    【解决方案2】:

    虽然 JimJones 的回答涵盖了如何创建一个点,但还有其他几个问题:

    1. st_distance 使用 CRS 的单位,3857 的单位是米。您正在搜索该位置 100m 内的条目
    2. 3857 在仅用于 DISPLAY 的投影中。不要在这个投影中计算距离,它们是高度扭曲的。要么使用合适的本地投影,要么使用geography 而不是geometrygeometry 默认使用米
    3. 理想情况下,您应该在几何/地理上有一个索引,然后您可以使用 ST_DWithin 而不是 ST_Distance,因为前者使用了空间索引
    4. 如果您的数据位于印度而不是最北端,则意味着您在创建点时已交换了经纬度

    查询可能变得类似于

    SELECT Offers.id, Address.id 
    FROM Offers 
      JOIN Address ON Address.id = Offers.addressId
    WHERE 
     ST_DWithin(ST_MakePoint(77.6185572, 12.9406589)::geography,
        Address.location::Geography, 100000);
    

    带有地理索引

    CREATE INDEX geogidx ON Address USING GIST((location::geography));
    

    【讨论】:

    • 非常好的观察! +1 关于第 3 点,我还添加了指向另一个答案的链接(许多关于距离的答案之一),我同意:ST_DWithin 将是一个更好的选择。欢呼
    • @JGH 非常感谢您的建议。根据您建议的更改,查询的外观如何。我是 Postgres 的新手,很难弄清楚这一点?
    • @JGH 感谢您的询问!最后一个问题,我应该以什么格式将 lat,long 值插入 Address.location 这是一个地理字段。
    猜你喜欢
    • 2016-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 2017-06-20
    相关资源
    最近更新 更多