i am trying to running this on my table
select ST_Distance (
select location from utenti where user_id=464,
select location from utenti where user_id=474604
);
having a location column of this type location geography(POINT, 4326)
i am getting a syntax error and i'm not understanding why.
how can i achieve my goal?
for example if i select that column in two queries for each users i get a data like this
"0101000020E61000001435F98F528125402AE5B512BAA34540"
and running:
select ST_Distance(%s, %s);
it works but the distance doesn't seem to be true. hm
As pointed out in the comments above you can rewrite the query as:
SELECT ST_Distance(a.geom, b.geom) FROM utenti a, utenti b WHERE a.user_id=464 AND b.user_id=474604;
BUT this will give you the distance in degrees (as that is what your points are stored as). So you will want to change your function to be:
SELECT ST_Distance_Sphere(a.geom, b.geom) FROM utenti a, utenti b WHERE a.user_id=464 AND b.user_id=474604;
ST_Distance_sphere will take some of the curvature of the Earth in to account and will return a distance in metres. If you require absolute accuracy and are not worried about speed you can account for all of the Earth's curvature by using st_distance_spheroid.
İf you polygon to point distance
select st_distance(
st_geomfromtext('POINT (0 0)'),
st_geomfromtext('POLYGON ((1 1, 2 1, 2 2, 1 2, 1 1))')
)
same base spatial geom column for
select st_distance(
st_geomfromtext(c.geom),
st_geomfromtext(b.geom)
) from city c , build b where b.c_ID=c.ID
Related
I am pretty new to PostGIS, PostgreSQL, and SQL, so please be patient.
I have a table 'highways' that looks like this:
Then I would like to sum the road lengths by type and grid cell to produce a table like this:
I have been able to sum the road lengths in one cell (or bounding box) with:
SELECT geom
round(SUM(
ST_Length(
ST_Intersection(geom, (SELECT geom FROM boundaries WHERE area_id=-1377803))::geography
))) AS "length (meters)", type
FROM highways
WHERE ST_Intersects(geom, (SELECT geom FROM boundaries WHERE area_id=-1377803))
GROUP BY type
ORDER BY "length (meters)" DESC
LIMIT 10;
And to create the grid with:
WITH grid AS (
SELECT (ST_SquareGrid(1, ST_Transform(geom,4326))).*
FROM boundaries
)
SELECT ST_AsText(geom)
FROM grid LIMIT 10;
I found of example for counting points here, and I could replicate it for counting the number of roads by cell like this:
SELECT COUNT(*), grid.geom
FROM
highways AS hwy
INNER JOIN
ST_SquareGrid(
1,
ST_SetSRID(ST_EstimatedExtent('highways', 'geom'), 4326)
) AS grid
ON ST_Intersects(hwy.geom, grid.geom)
GROUP BY grid.geom, hwy.type LIMIT 10;
But I couldn't extrapolate it for what I intend to do. Any help with this is highly appreciated.
I have hundreds of polygon (circles) where some of the polygon intersected with each others. This polygon is come from single feature layer. What I am trying to do is to delete the intersected circles.
It is similar to this question: link, but those were using two different layer. In my case the intersection is from single feature layers.
If I understood your question right, you just need to either create a CTE or simple subquery.
This might give you a good idea of how to solve your issue:
CREATE TABLE t (id INTEGER, geom GEOMETRY);
INSERT INTO t VALUES
(1,'POLYGON((-4.54 54.30,-4.46 54.30,-4.46 54.29,-4.54 54.29,-4.54 54.30))'),
(2,'POLYGON((-4.66 54.16,-4.56 54.16,-4.56 54.14,-4.66 54.14,-4.66 54.16))'),
(3,'POLYGON((-4.60 54.19,-4.57 54.19,-4.57 54.15,-4.60 54.15,-4.60 54.19))'),
(4,'POLYGON((-4.40 54.40,-4.36 54.40,-4.36 54.38,-4.40 54.38,-4.40 54.40))');
This data set contains 4 polygons in total and two of them overlap, as seen in the following picture:
Applying a CTE with a subquery might give you what you want, which is the non-overlapping polygons from the same table:
SELECT id, ST_AsText(geom) FROM t
WHERE id NOT IN (
WITH j AS (SELECT * FROM t)
SELECT j.id
FROM j
JOIN t ON t.id <> j.id
WHERE ST_Intersects(j.geom,t.geom)
);
id | st_astext
----+---------------------------------------------------------------------
1 | POLYGON((-4.54 54.3,-4.46 54.3,-4.46 54.29,-4.54 54.29,-4.54 54.3))
4 | POLYGON((-4.4 54.4,-4.36 54.4,-4.36 54.38,-4.4 54.38,-4.4 54.4))
(2 rows)
You can write quite clear delete statement using EXISTS clause. You literally want to delete the rows, for which there exists other rows which geometry intersects:
DELETE
FROM myTable t1
WHERE EXISTS (SELECT 1 FROM myTable t2 WHERE t2.id <> t1.id AND ST_Intersects(t1.geom, t2.geom))
A follow on from this question: ST_3DClosestPoint returning multiple points
1) I have a xyz target point stored as a geom, I want to update the row with the 3Ddistance to the nearest obs point in another table. So find the nearest obs point and then update the target point with the distance.
expected result for the target point:
id|geom|3Ddistance_To_Nearest_Point_In_Obs_Table
obs table:
id|geom
e.g. 100 records
2) To complicate matters, I also want to select n-neighbours from the obs table (lets say 10 for example) and calculate the average distance and update the target table.
expected target result:
id|geom|average_3Ddistance
I've been trying to alter the former example, but no joy, any ideas?
Thanks
If collections are static then you can CTAS (create table as select) your results instead of updating it.
create table new_table as
select t2.id, t2.geom, min(3ddistance) min_3DDistance, avg(3ddistance) avg_3ddistance
from target t2,
lateral (select t.id, st_3ddistance(o.geom, t.geom) 3ddistance
from obs o, target t
where t2.id=t.id
order by st_3ddistance(o.geom, t.geom) limit 10) a
group by t2.id, t2.geom;
or if you want to update
update target
set (average_3ddistance, min_3ddistance)=(
from (select id, min(3ddistance) min_3DDistance, avg(3ddistance) avg_3ddistance
from (select t.id, st_3ddistance(o.geom, t.geom) 3ddistance
from obs o, target t
where t2.id=t.id
order by st_3ddistance(o.geom, t.geom) limit 10) a
group by id) b
where b.id=t.id;
I have a point on line with two polygons on both sides. The scenario is shown in the following:
Now, I would like to compute the perpendicular distance between two polygons (for example, yellow line) using a PostGIS query. I was wondering if someone could suggest me how to do that?
EDIT1:
Above given scenario was an example. There can be complications in scenarios having streets, points and polygons. For example, the side parallel to street may not always be there.
Scenario_2:
Scenario_3:
EDIT2
Scenario_4
I want to calculate the perpendicular distance only where there is a point on line. I understand there can be exceptions in this, as point by #JGH.
Assuming your data is projected and that the distance between the points and the two nearest polygon is the one you are looking for, you can compute the distance from each point to the two polygons and make the sum.
1) compute the distance. Restrict the search to a reasonable distance, maybe twice the expected largest distance. Make sure the geometries are indexed!!
SELECT pt.gid point_gid, plg.gid polygon_gid, ST_Distance(pt.geom, plg.geom) distance
FROM pointlayer pt, polygonlayer plg
WHERE ST_Distance(pt.geom, plg.geom) < 50
ORDER BY pt.gid, ST_Distance(pt.geom, plg.geom);
2) For each point, get the two closest polygons using the partition function
SELECT
point_gid, polygon_gid, distance
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY point_gid ORDER BY distance asc) AS rank,
t.*
FROM
[distanceTable] t) top_n
WHERE
top_n.rank <= 2;
3) agregate the result and keep track of which polygons were used
select point_gid,
sum(distance) streetwidth,
string_agg(polygon_gid || ' - ' || distance,';') polyid_dist_info
from [top_2_dist dst]
group by dst.point_gid;
All together:
SELECT
point_gid,
sum(distance) streetwidth,
string_agg(polygon_gid || ' - ' || distance,';') polyid_dist_info
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY point_gid ORDER BY distance asc) AS rank,
t.*
FROM
( SELECT pt.gid point_gid,
plg.gid polygon_gid,
ST_Distance(pt.geom, plg.geom) distance
FROM pointlayer pt, polygonlayer plg
WHERE ST_Distance(pt.geom, plg.geom) < 50
) t
) top_n
WHERE
top_n.rank <= 2
GROUP BY point_gid;
Using PostgreSQL 9.5.2, PostGIS 2.2, given the following geo coordinates:
'SRID=4326;POINT(24.8713597 60.1600568)' -- Origin
'SRID=4326;POINT(24.87717970 60.19824480)' -- Destination A
'SRID=4326;POINT(24.91281220 60.15821350)' -- Destination B
'SRID=4326;POINT(24.91404950 60.16373390)' -- Destination C
'SRID=4326;POINT(24.91552820 60.16129280)' -- Destination D
Sorting by "geographical" distance (ST_Distance method):
select name, st_distance('SRID=4326;POINT(24.8713597 60.1600568)'::geography, geo)
from (select 'SRID=4326;POINT(24.87717970 60.19824480)'::geography as geo, 'A' as name
union select 'SRID=4326;POINT(24.91281220 60.15821350)'::geography as geo, 'B' as name
union select 'SRID=4326;POINT(24.91404950 60.16373390)'::geography as geo, 'C' as name
union select 'SRID=4326;POINT(24.91552820 60.16129280)'::geography as geo, 'D' as name) tmp
order by 2;
Results in:
B,2311.075069284
C,2405.58508757
D,2456.504535795
A,4266.971129052
Whereas sorting by "geometrical" 2D distance (<-> Operator):
select name, 'SRID=4326;POINT(24.8713597 60.1600568)'::geometry <-> geom
from (select 'SRID=4326;POINT(24.87717970 60.19824480)'::geometry as geom, 'A' as name
union select 'SRID=4326;POINT(24.91281220 60.15821350)'::geometry as geom, 'B' as name
union select 'SRID=4326;POINT(24.91404950 60.16373390)'::geometry as geom, 'C' as name
union select 'SRID=4326;POINT(24.91552820 60.16129280)'::geometry as geom, 'D' as name) tmp
order by 2;
Results in:
A,0.03862894955858695
B,0.041493463474867306
C,0.042847871457636175
D,0.04418579056948194
... And I would expect the order to be exactly the same.
What am I missing?
You are making the calculations at 60 degrees of latitude. Here a degree of latitude is much larger than a degree of longitude. Specifically, at 60 degrees of latitude a degree of latitude is 111.412km, while a degree of longitude is 55.800km. This means that the separation in longitude value is much more important than the separation in latitude.
A 24.87717970 - 24.8713597 = 0.006...
B 24.91281220 - ... = 0.041...
C 24.91404950 - ... = 0.043...
D 24.91552820 - ... = 0.044
Which nicely corresponds to your result.