Skip to main content
added 65 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
  SET  stop_id = (
    SELECT
      stops.stop_id
    FROM
      stops
    ORDER BY
           gps.geom <-> stops.geom
    LIMIT
      1
  )
;

[*] Just to give an example on that; consider a SELECT instead to find the closest stop to each gps point using JOIN LATERAL:

SELECT
  a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM  
  gps AS a
  CROSS JOIN LATERAL (
    SELECT
      stops.stop_id
    FROM
      stops
    ORDER BY
         a.geom <-> stops.geom
    LIMIT
      1
  ) AS b
;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
  SET  stop_id = (
    SELECT stops.stop_id
    FROM   stops
    ORDER BY
           gps.geom <-> stops.geom
    LIMIT  1
  )
;

[*] Just to give an example on that; consider a SELECT instead to find the closest stop to each gps point using JOIN LATERAL:

SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM   gps AS a
CROSS JOIN LATERAL (
  SELECT stops.stop_id
  FROM   stops
  ORDER BY
         a.geom <-> stops.geom
  LIMIT  1
) AS b
;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
  SET  stop_id = (
    SELECT
      stops.stop_id
    FROM
      stops
    ORDER BY
      gps.geom <-> stops.geom
    LIMIT
      1
  )
;

[*] Just to give an example on that; consider a SELECT instead to find the closest stop to each gps point using JOIN LATERAL:

SELECT
  a.gps_id,
  a.measured_timestamp,
  a.geom,
  b.stop_id
FROM 
  gps AS a
  CROSS JOIN LATERAL (
    SELECT
      stops.stop_id
    FROM
      stops
    ORDER BY
      a.geom <-> stops.geom
    LIMIT
      1
  ) AS b
;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

deleted 1144 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
  SET  stop_id = (
    SELECT stops.stop_id
    FROM   stops
    ORDER BY
           gps.geom <-> stops.geom
    LIMIT  1
  ) 
;

*You are a very experienced PostGIS user; still, let me add some notes on distances and the KNN operator ,)*

For better precision, consider casting to *geography*; the `` operator then measures on a sphere, while `ST_Distance` uses the actual spheroid. In my experience, for points the `` operator tends to perform only slightly faster than with plain old `ST_Distance` with *geography* type and a limit condition (check if the index scan actually kicks in with ``; it should consider the passed in geometry as a constant, but sometimes it doesn't for me).

If the tables are large, you can add a `WHERE ST_DWithin(gps.geom, stops.geom, )` (or, if the planner denies an *index only scan*, use `ST_Expand(gps.geom, ) && stops.geom`; for point on point KNN and *geometry* type, this is ultimatively fast) to only compare those `stops` in each `gps` points' vicinity (note that the distance given uses the CRS units (i.e. degrees for *EPSG:4326*) for *geometry*, but meter for *geography*).


 
[*] Just to give an example on that; consider a `SELECT` instead to find the closest `stop` to each `gps` point using `JOIN LATERAL`:

[*] Just to give an example on that; consider a SELECT instead to find the closest stop to each gps point using JOIN LATERAL:

SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM   gps AS a
CROSS JOIN LATERAL (                         -- you can use 'CROSS JOIN LATERAL' without 'ON true',
  SELECT stops.stop_id                
  --FROM but I getstops
 slightly fasterORDER resultsBY
 this way
  FROM stops
  ORDER BY a.geom <-> stops.geom
  LIMIT  1
) AS b
ON true;;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
SET stop_id = (
  SELECT stops.stop_id
  FROM stops
  ORDER BY gps.geom <-> stops.geom
  LIMIT 1
);

*You are a very experienced PostGIS user; still, let me add some notes on distances and the KNN operator ,)*

For better precision, consider casting to *geography*; the `` operator then measures on a sphere, while `ST_Distance` uses the actual spheroid. In my experience, for points the `` operator tends to perform only slightly faster than with plain old `ST_Distance` with *geography* type and a limit condition (check if the index scan actually kicks in with ``; it should consider the passed in geometry as a constant, but sometimes it doesn't for me).

If the tables are large, you can add a `WHERE ST_DWithin(gps.geom, stops.geom, )` (or, if the planner denies an *index only scan*, use `ST_Expand(gps.geom, ) && stops.geom`; for point on point KNN and *geometry* type, this is ultimatively fast) to only compare those `stops` in each `gps` points' vicinity (note that the distance given uses the CRS units (i.e. degrees for *EPSG:4326*) for *geometry*, but meter for *geography*).


[*] Just to give an example on that; consider a `SELECT` instead to find the closest `stop` to each `gps` point using `JOIN LATERAL`:
SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM gps AS a
JOIN LATERAL (                         -- you can use 'CROSS JOIN LATERAL' without 'ON true',
  SELECT stops.stop_id                 -- but I get slightly faster results this way
  FROM stops
  ORDER BY a.geom <-> stops.geom
  LIMIT 1
) AS b
ON true;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
  SET  stop_id = (
    SELECT stops.stop_id
    FROM   stops
    ORDER BY
           gps.geom <-> stops.geom
    LIMIT  1
  ) 
;
 

[*] Just to give an example on that; consider a SELECT instead to find the closest stop to each gps point using JOIN LATERAL:

SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM   gps AS a
CROSS JOIN LATERAL (
  SELECT stops.stop_id 
  FROM   stops
  ORDER BY
         a.geom <-> stops.geom
  LIMIT  1
) AS b
;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

deleted 2 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each rows SET valueprocessing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
SET stop_id = (
  SELECT stops.stop_id
  FROM stops
  ORDER BY gps.geom <-> stops.geom
  LIMIT 1
);

*You are a very experienced PostGIS user; still, let me add some notes on distances and the KNN operator ,)*

For better precision, consider casting to *geography*; the `` operator then measures on a sphere, while `ST_Distance` uses the actual spheroid. In my experience, for points the `` operator tends to perform only slightly faster than with plain old `ST_Distance` with *geography* type and a limit condition (check if the index scan actually kicks in with ``; it should consider the passed in geometry as a constant, but sometimes it doesn't for me).

If the tables are large, you can add a `WHERE ST_DWithin(gps.geom, stops.geom, )` (or, if the planner denies an *index only scan*, use `ST_Expand(gps.geom, ) && stops.geom`; for point on point KNN and *geometry* type, this is ultimatively fast) to only compare those `stops` in each `gps` points' vicinity (note that the distance given uses the CRS units (i.e. degrees for *EPSG:4326*) for *geometry*, but meter for *geography*).


[*] Just to give an example on that; consider a `SELECT` instead to find the closest `stop` to each `gps` point using `JOIN LATERAL`:
SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM gps AS a
JOIN LATERAL (                         -- you can use 'CROSS JOIN LATERAL' without 'ON true',
  SELECT stops.stop_id                 -- but I get slightly faster results this way
  FROM stops
  ORDER BY a.geom <-> stops.geom
  LIMIT 1
) AS b
ON true;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each rows SET value to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
SET stop_id = (
  SELECT stops.stop_id
  FROM stops
  ORDER BY gps.geom <-> stops.geom
  LIMIT 1
);

*You are a very experienced PostGIS user; still, let me add some notes on distances and the KNN operator ,)*

For better precision, consider casting to *geography*; the `` operator then measures on a sphere, while `ST_Distance` uses the actual spheroid. In my experience, for points the `` operator tends to perform only slightly faster than with plain old `ST_Distance` with *geography* type and a limit condition (check if the index scan actually kicks in with ``; it should consider the passed in geometry as a constant, but sometimes it doesn't for me).

If the tables are large, you can add a `WHERE ST_DWithin(gps.geom, stops.geom, )` (or, if the planner denies an *index only scan*, use `ST_Expand(gps.geom, ) && stops.geom`; for point on point KNN and *geometry* type, this is ultimatively fast) to only compare those `stops` in each `gps` points' vicinity (note that the distance given uses the CRS units (i.e. degrees for *EPSG:4326*) for *geometry*, but meter for *geography*).


[*] Just to give an example on that; consider a `SELECT` instead to find the closest `stop` to each `gps` point using `JOIN LATERAL`:
SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM gps AS a
JOIN LATERAL (                         -- you can use 'CROSS JOIN LATERAL' without 'ON true',
  SELECT stops.stop_id                 -- but I get slightly faster results this way
  FROM stops
  ORDER BY a.geom <-> stops.geom
  LIMIT 1
) AS b
ON true;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

No need for JOIN LATERAL (or do you really just want to use it?); an UPDATE will pass each processing row to the following query, which is the same concept as using a JOIN LATERAL.[*]

Try

UPDATE gps
SET stop_id = (
  SELECT stops.stop_id
  FROM stops
  ORDER BY gps.geom <-> stops.geom
  LIMIT 1
);

*You are a very experienced PostGIS user; still, let me add some notes on distances and the KNN operator ,)*

For better precision, consider casting to *geography*; the `` operator then measures on a sphere, while `ST_Distance` uses the actual spheroid. In my experience, for points the `` operator tends to perform only slightly faster than with plain old `ST_Distance` with *geography* type and a limit condition (check if the index scan actually kicks in with ``; it should consider the passed in geometry as a constant, but sometimes it doesn't for me).

If the tables are large, you can add a `WHERE ST_DWithin(gps.geom, stops.geom, )` (or, if the planner denies an *index only scan*, use `ST_Expand(gps.geom, ) && stops.geom`; for point on point KNN and *geometry* type, this is ultimatively fast) to only compare those `stops` in each `gps` points' vicinity (note that the distance given uses the CRS units (i.e. degrees for *EPSG:4326*) for *geometry*, but meter for *geography*).


[*] Just to give an example on that; consider a `SELECT` instead to find the closest `stop` to each `gps` point using `JOIN LATERAL`:
SELECT a.gps_id,
       a.measured_timestamp,
       a.geom,
       b.stop_id
FROM gps AS a
JOIN LATERAL (                         -- you can use 'CROSS JOIN LATERAL' without 'ON true',
  SELECT stops.stop_id                 -- but I get slightly faster results this way
  FROM stops
  ORDER BY a.geom <-> stops.geom
  LIMIT 1
) AS b
ON true;

Each row in gps is now passed individually and subsequentially to the JOIN LATERAL sub-query to be processed; this (sort of) mimicks the UPDATE command (note how it is the same sub-query).

added 109 characters in body; added 44 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
edited body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
edited body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
added 6 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
added 10 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
added 712 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
added 196 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
added 273 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
added 302 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57
Loading