I am a student and working on a query to update all records in a table with the distance from a specific point (a town). I am using Pgadmin4 with a postgreSQL/postgis database.
I created a select query that calculates the distance for the point of origin (Stockholm) to all other cities in the database (points). Next I want to update the table for all records with this calculated value in km’s.
I tried this query. If I run the Select part the query gives the names and distance to Stockholm from all other cities in the database. I however haven’t been able to create a query to update all records at once.
UPDATE cities2
SET dist = distance
Where distance = (SELECT b.name, ST_Distancesphere(a.geom, b.geom)/1000
From cities2 a, cities2 b
Where a.name='Stockholm' and b.name in (select name from cities2));
I get the error that column distance does not excist, which is correct because I tried to make it a variable. dist is the field I wish to update for each record (city) in the table with the distance in km’s from Stockholm
2
Answers
and b.name in (select name from cities2)
doesn’t make much sense beyond filtering out rows wherename is null
– if that’s the intention, use that instead.=
operator that can comparedistance = (name, distance)
.alter table cities2 alter column dist rename to distance_from_stockholm;
to make it clearer if not for someone else, then at least for you a week from now.There is no such thing as a variable in the PostgreSQL SQL dialect, outside of its procedural languages.
UPDATE
logic might be somewhat counter-intuitive, but the most important quality is that anUPDATE
can be inherently correlated, meaning that it exposes a row to the call; think of it as a sequential traversal of the table – excluding any row that match theWHERE
filter statement – where the following statement blocks can refer to column values in the current row.The
SET
clause can itself be a (correlated) sub-query, or resembling aSELECT
set of aFROM
item (or aCROSS JOIN
ed combination thereof), even with a self-join.With that in mind, your requirement can be expressed in a variety of ways; some examples:
In this case they should all resolve in a similar query plan, at least in terms of performance. For other scenarios, one way may vastly outperform the other, but that is outside the scope of this.
In cases of a self-join it is good practice – or even required – to add a filter condition to avoid updating self-referenced rows; maybe you don’t want to update the
dist
value of the rowWHERE name = 'Stockholm'
!? Again, in this case, addingWHERE c1.name <> 'Stockholm'
does the trick, but usually you would try to target an indexed or Primary Key column.I prefer the more idiomatic
ST_Distance
on the (casted)GEOGRAPHY
type; strictly speaking, the results between this call andST_DistanceSphere
are not equal, as the two-parameter call ofST_Distance
withGEOGRAPHY
-typed values defaults to spheroidal distance calculations – which are, in fact, more precise.