I have a table of LineString features and I wish to identify which lines intersect.
ST_Intersects(geom1, geom2) needs two geometries from two different tables. Right now i am creating two different references back to the same table and it just doesn't seem like the right approach.
I am currently using the following bit of code, and I am curious if there is some better way of accomplishing this. Surely running an intersect on features within one table must be a common task.
SELECT a.link_id as a_link_id,
b.link_id as b_link_id,
st_intersects(a.geom, b.geom)
INTO results_table
FROM table_one a, table_one b
WHERE a.link_id != b.link_id;
PostGIS 2.4.0
PG 9.6.5
Your approach is ok. The only problem with this is that it will return duplicate records. e.g if two lines are intersecting with IDs 10 and 11 respectively. There will be two rows for each ID in the result, even the lines are intersecting only once. You can cater this with > or < operator in place of !=. And intersect condition comes in where i guess
SELECT a.link_id as a_link_id,
b.link_id as b_link_id
INTO results_table
FROM table_one a, table_one b
WHERE a.link_id < b.link_id AND st_intersects(a.geom, b.geom)
Related
I'm working on a query using the PostGIS extension that implements a 'spatial join' work. Running the query took an incredibly long time and failed in the end. The query is as follows:
CREATE INDEX buffer_table_geom_idx ON buffer_table USING GIST (geom);
CREATE INDEX point_table_geom_idx ON point_table USING GIST (geom);
SELECT
point_table.*,
buffer_table.something
FROM
point_table
LEFT JOIN buffer_table ON ST_Intersects (buffer_table.geom, point_table.geom);
where the point_table stands for a table that contains over 10 million rows of point records; the buffer_table stands for a table that contains only one multi-polygon geometry.
I would want to know if there is anything wrong with my code and ways to adjust. Thanks in advance.
With a LEFT JOIN you're going through every single record of point_table and therefore ignoring the index. Try this and see the difference:
SELECT point_table.*
FROM point_table
JOIN buffer_table ON ST_Contains(buffer_table.geom, point_table.geom);
Divide and conquer with ST_SubDivide
Considering the size of your multipolygon (see comments), it might be interesting to divide it into smaller pieces, so that the number of vertices for each containment/intersection calculation also gets reduced, consequently making the query less expensive.
First divide the large geometry into smaller pieces and store in another table (you can also use a CTE/Subquery)
CREATE TABLE buffer_table_divided AS
SELECT ST_SubDivide(geom) AS geom FROM buffer_table
CREATE INDEX buffer_table_geom_divided_idx ON buffer_table_divided USING GIST (geom);
.. and perform your query once again against this new table:
SELECT point_table.*
FROM point_table
JOIN buffer_table_divided d ON ST_Contains (d.geom, point_table.geom);
Demo: db<>fiddle
What Im looking to do is select data from a postgres table, which does not appear in another. Both tables have identical columns, bar the use of boolean over Varchar(1) but the issue is that the data in those columns do not match up.
I know I can do this with a SELECT EXCEPT SELECT statement, which I have implemented and is working.
What I would like to do is find a method to flag the columns that do not match up. As an idea, I have thought to append a character to the end of the data in the fields that do not match.
For example if the updateflag is different in one table to the other, I would be returned '* f' instead of 'f'
SELECT id, number, "updateflag" from dbc.person
EXCEPT
SELECT id, number, "updateflag":bool from dbg.person;
Should I be joining the two tables together, post executing this statement to identify the differences, from whats returned?
I have tried to research methods to implement this but have no found anything on the topic
I prefer a full outer join for this
select *
from dbc.person p1
full join dbg.person p2 on p1.id = p2.id
where p1 is distinct from p2;
The id column is assumed the primary key column that "links" the two tables together.
This will only return rows where at least one column is different.
If you want to see the differences, you could use a hstore feature
select hstore(p1) - hstore(p2) as columns_diff_p1,
hstore(p2) - hstore(p1) as columns_diff_p2
from dbc.person p1
full join dbg.person p2 on p1.id = p2.id
where p1 is distinct from p2;
In a query today I wanted to select rows that had a particular company name in either of two columns from two different tables. I did it like
WHERE (N.COMPANY LIKE '%ACME%' OR C.COMPANY LIKE '%ACME%')
First, it took 20 minutes to run, which was odd because if I only filtered on one of the columns it took about 10 seconds. Second, when it finished, values for some columns in some rows were NULL when I know for a fact there are values in the database for those columns in those records. So what is going on here? Why can't SQL do the OR on two columns from two tables?
(I worked around it with a UNION - I ran it for C.COMPANY LIKE '%ACME%' and UNIONED it with a SELECT... WHERE N.COMPANY LIKE '%ACME%')
It is bad practice to mix up the JOIN and the WHERE keyword in one single query, because WHERE is an INNER JOIN behind the scenes. From my experience this often results in uncontrolled joins which one don't want.
Try to place your LIKE's after the join of the corresponding tables directly like this:
...
JOIN N ON <Your existing relationship> AND N.COMPANY LIKE '%ACME%'
...
JOIN C ON <Your existing relationship> AND C.COMPANY LIKE '%ACME%'
...
I have two tables, table1 and table2, both of which contain columns that store postgis geometries. What I want to do is see where the geometry stored in any row of table2 geometrically intersects with the geometry stored in any row of table1 and update a count column in table1 with the number of intersections. Therefore, if I have a geometry in row 1 of table1 that intersects with the geometries stored in 5 rows in table2, I want to store a count of 5 in a separate column in table one. The tricky part for me is that I want to do this for every row of column 1 at the same time.
I have the following:
UPDATE circles SET intersectCount = intersectCount + 1 FROM rectangles
WHERE ST_INTERSECTS(cirlces.geom, rectangles.geom);
...which doesn't seem to be working. I'm not too familiar with postgres (or sql in general) and I'm wondering if I can do this all in one statement or if I need a few. I have some ideas for how I would do this with multiple statements (or using for loop) but I'm really looking for a concise solution. Any help would be much appreciated.
Thanks!
something like:
update t1 set ctr=helper.ctr
from (
select t1.id, count(*) as cnt
from t1, t2
where st_intersects(t1.col, t2.col)
group by t1.id
) helper
where helper.id=t1.id
?
btw: Your version does not work, because a row can get updated only once in a single update statement.
I have two tables. First with points, and second with polygons. I need to find out which points are in required polygon according to the attribute gid.
Using query: SELECT table1.* FROM table1, table2 WHERE table2.gid=1 AND ST_Contains(table2.geom2, table1.geom1);
What I get is empty table (only columns without data)...
Tnx
Are you sure there are any intersecting points? Try
SELECT COUNT(*) FROM table2 WHERE table2.gid=1
It should return 1.
Another thing you could try is using ST_Intersects instead of ST_Contains.
Otherwise, you might need to post some data dumps of data you think should match.