Search code examples
postgresqlpostgis

How to factor this postgis query with subquery?


I have a query to found POIs around trace :

SELECT
      ptb.* AS pois
      FROM traces tr, pois pta, pois ptb
      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) / ST_Length(tr.path, false),
        ST_LineLocatePoint(tr.path, pta.lonlat::geometry) + (#{end_point} * 1000) / ST_Length(tr.path, false)
        )::geography,
        ptb.lonlat::geography,
        4000)

How can I use subquery for :
ST_LineLocatePoint(tr.path, pta.lonlat::geometry)
ST_Length(tr.path, false)

EDIT :

   WITH RECURSIVE locate_point_a AS (
      select ST_LineLocatePoint(tr.path, pta.lonlat::geometry) AS locate_point_a
      FROM traces tr, pois pta
      WHERE tr.id = 2
      AND pta.id = 2
      )
  SELECT
    ptb.* AS pois
    FROM traces tr, pois pta, pois ptb, locate_point_a
    WHERE tr.id = 2
      AND pta.id = 2
      AND ST_DWithin(
      ST_LineSubstring(
      tr.path,
      locate_point_a + (25 * 1000) / ST_Length(tr.path, false),
      locate_point_a + (250 * 1000) / ST_Length(tr.path, false)
      )::geography,
      ptb.lonlat::geography,
      4000)
    SQL

Solution

  • This should do the same (but I do not understand the logic, TBH):


    SELECT
          ptb.* -- AS pois
    FROM  pois ptb
    WHERE EXISTS (
          SELECT *
          FROM traces tr
          JOIN pois pta ON ST_DWithin(
                    ST_LineSubstring( tr.path
                            , ST_LineLocatePoint(tr.path, pta.lonlat::geometry) + (#{dist} * 1000) / ST_Length(tr.path, false)
                            , ST_LineLocatePoint(tr.path, pta.lonlat::geometry) + (#{end_point} * 1000) / ST_Length(tr.path, false)
                            )::geography
                    , ptb.lonlat::geography
                    , 4000
                    )
          WHERE tr.id = #{trace.id}
            AND pta.id = #{poi.id}
            ;