【问题标题】:Postgis : How to make only one query with 2 queriesPostgis:如何只用 2 个查询进行一次查询
【发布时间】:2019-11-02 18:10:09
【问题描述】:

跟踪数据库:

痕迹是远足路径

  create_table "traces", force: :cascade do |t|
    t.string "name"
    t.geometry "path", limit: {:srid=>4326, :type=>"line_string"}
  end

Pois 数据库:

Poi 是一个兴趣点(城市、城堡……)

create_table "pois", force: :cascade do |t|
    t.string "address"
    t.string "address2"
    t.integer "zip_code"
    t.string "city"
    t.string "department"
    t.string "region"
    t.float "latitude"
    t.float "longitude"
    t.geography "lonlat", limit: {:srid=>4326, :type=>"st_point", :geographic=>true}
  end

通过第一个查询,我从一个 POI(pta => poi1) 获得围绕一个轨道 (tr) 的 POI(ptb => poi2) 数组

      SELECT
        ptb.* AS pois
        FROM traces tr, pois pta, pois ptb, locate_point_a
        WHERE tr.id = #{trace.id}
          AND pta.id = #{poi1.id}
          AND ST_DWithin(
          ST_LineSubstring(
          tr.path,
          ST_LineLocatePoint(tr.path, pta.lonlat::geometry) + (25 * 1000) / ST_Length(tr.path, false),
          ST_LineLocatePoint(tr.path, pta.lonlat::geometry) + (250 * 1000) / ST_Length(tr.path, false)
          )::geography,
          ptb.lonlat::geography,
          4000)

通过第二个查询,我计算了一个 POI 和另一个 POI 之间的距离(在赛道上)

      SELECT
        ST_Distance(tr.path::geography, pta.lonlat::geography) +
        ST_Distance(tr.path::geography, ptb.lonlat::geography) +
        ST_Length(ST_LineSubstring(
          tr.path,
          least(ST_LineLocatePoint(tr.path, pta.lonlat::geometry), ST_LineLocatePoint(tr.path, ptb.lonlat::geometry)),
          greatest(ST_LineLocatePoint(tr.path, pta.lonlat::geometry), ST_LineLocatePoint(tr.path, ptb.lonlat::geometry))),false)  AS dst_line
        FROM traces tr, pois pta, pois ptb, locate_point_a, locate_point_b
        WHERE tr.id = #{trace.id}
          AND pta.id = #{poi1.id}
          AND ptb.id = #{poi2.id}

我只想进行一次查询并获取轨道周围的 POI 列表(按距离排序)以及一个 POI 到列表中所有其他 POI 的距离(来自第一个查询)。

例如:

我从一个城镇 (pta) 开始。我想步行 25 公里(距离),想知道在哪里可以找到在这个距离附近睡觉的旅馆。通过第一个查询,我可以获得一个列表,其中包含跟踪周围 4000 m 的所有酒店 (ptb)。

对于第一个查询的结果,我得到一个 poi.ids 的无序列表:[1, 7, 8, 3]

但是,我还需要知道并显示我的起点 (pta) 和每家酒店 (ptb) 之间的确切公里数。它们是在 21 公里、22 公里还是 24 公里……?

因此,通过第二个查询的结果,我得到了每个 poi 的信息(来自第一个查询):
[1 => 21.6] [7 => 26.2] [8 => 21.2] [3 => 20.4 ]

这两个查询完成了这项工作(但分别)。我需要有相同的结果,但只有一个查询。

有里程的所有酒店的有序列表:

[3 => 20,4 , 8 => 21.2 ,  1=> 21,6 , 7 => 26,2]

【问题讨论】:

  • FROM traces tr, pois pta 这是 Carthesian 产品吗? 使用JOIN运算符来连接表。
  • 嗨,Ben,到底是什么问题?请查看帮助部分How to Ask。为您的问题使用该模板会大大增加您获得满意答案的机会。确保包括表 DDL、示例数据(作为文本而不是图像)以及该数据的预期输出。还包括您的首字母缩略词的含义可能会很有用。究竟什么是兴趣点。就 JOIN 而言,它更好,但实际上没有必要。但是,这样做可能会为您提供更多了解查询的受众。
  • @wildplasser 没有用于痕迹和 pois 的 Carthesian 产品。 Traces 和 pois 有任何关系。
  • @Belayer 我用一个例子和更多信息编辑了我的帖子。
  • “pois”表中没有名为“id”的列。请在您的问题中添加实际的 DDL。

标签: ruby-on-rails postgresql postgis


【解决方案1】:
  SELECT
    ST_Distance(tr.path::geography, pta.lonlat::geography) +
    ST_Distance(tr.path::geography, poi.lonlat::geography) +
    ST_Length(ST_LineSubstring(
      tr.path,
      least(ST_LineLocatePoint(tr.path, pta.lonlat::geometry), ST_LineLocatePoint(tr.path, poi.lonlat::geometry)),
      greatest(ST_LineLocatePoint(tr.path, pta.lonlat::geometry), ST_LineLocatePoint(tr.path, poi.lonlat::geometry))),false)  AS dst_line, poi.*
  FROM traces tr, pois pta, (
    SELECT poi.* AS pois
    FROM traces tr, pois pta, pois poi
    WHERE tr.id = #{trace.id}
    AND pta.id = #{poi.id}
    AND ST_DWithin(ST_LineSubstring(
            tr.path,
            ST_LineLocatePoint(tr.path, pta.lonlat::geometry) + (#{dist} * 1000) / (tr.length * 1000) ,
            1)::geography,
            poi.lonlat::geography,
            2000)
      ) as poi
    WHERE tr.id = #{trace.id}
    AND pta.id = #{poi.id}
    AND poi.id = poi.id
    ORDER BY dst_line ASC

现在,我需要优化它:D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 2014-02-27
    • 2021-11-07
    • 2019-06-10
    • 2022-11-25
    相关资源
    最近更新 更多