Spatial Join in SQL Server - sql-server

I come from a mining and exploration background. I have a list of points (with ID and X and Y coordinates).
Example
I have another table which contains polygons (claim numbers).
I am trying to find out which points fall within which polygons. My coordinates are in UTM Projection.
Thank you in advance!
I was trying the following code however my query is not returning results.
SELECT
pg.claim_number,
p.DHId
FROM leasehold as pg
JOIN
(SELECT
DHId,
X,
Y,
geometry::STPointFromText('POINT(',X,' ',Y,'), 0) AS [geom]
FROM collar
WHERE X is not null AND
Y is not null AND
claim_number is null) AS p
ON pg.Shape.STIntersects(p.geom) = 1
I was expecting to get a list with claim_number from polygon table which each DHId from point table intersects or falls within.

It looks like there just a syntax/quoting issue. I cleaned it up a bit and replaced STPointFromText with Point which is an MS-specific extension but doesn't require you to create WKT just to get a point. But that's really all I changed - I'd expect your general approach to work.
SELECT
pg.claim_number,
p.DHId
FROM leasehold as pg
JOIN (
SELECT
DHId,
X,
Y,
geometry::Point(X, Y, 0) AS [geom]
FROM collar
WHERE X is not null AND
Y is not null AND
claim_number is null
) AS p
ON pg.Shape.STIntersects(p.geom) = 1;
That said, I would expect this to not be super performant. You're creating the points on the fly and so will be incurring that cost at run time. As such, there's no way to put a spatial index on that data. If you can, I'd suggest adding a column to your collar table that is the geometry point and, as I implied, put a spatial index on it. Also, if there's not an index on the leasehold.Shape column, I'd put one there as well.

Related

Delphi, code example code getting list of overlapping polygons with SQL Server Spatial

The overlap between polygons can be evaluated using SQL Server spatial .STContains function (https://learn.microsoft.com/en-us/sql/t-sql/spatial-geometry/stcontains-geometry-data-type?view=sql-server-ver16&viewFallbackFrom=sql-server-ver18)
Can I get some code sample to get the list of polygons located inside a given polygon (the record index should be the query parameter), return a list of records inside this polygon?
select *
from table
where PolygonsInside (RecordIndex = 1)
How to get to this SQL query?
Your description ("overlap between polygons") doesn't necessarily match the function you've chosen (from the same documentation you've linked to, STContains() "Returns 1 if a geometry instance completely contains another geometry instance.".); STIntersects() may be a better choice.
Regardless of any of that, here's a query you'd write to find any polygon from a table that overlaps given the ID of another polygon in the same table.
select overlaps.ID, overlaps.Polygon
from PolygonTable as given
join PolygonTable as other
on other.Polygon.STIntersects(given.Polygon) = 1
and other.ID <> given.ID
where given.ID = 1;
That is, if you provide an ID of 1, that query will find any polygon in the table that intersects with that. Note, I've added a predicate in the join so as not to also return the polygon that has the ID provided - that may or may not be what you want but it's easily removed if you do want to return that one.

Using SQL Server spatial queries, how to select a shape that is produced by intersecting two other shapes and calculate its area?

Consider the following query:
SELECT b.*
FROM dbo.BndPrimarySchoolZone b
WHERE b.ncessch IN ( 250315000417, 250315000421 );
It produces two rows, returning some descriptive data along with two shapes (Shape column is of data type geometry):
In the "Spatial results" tab you can see that these two shapes overlap:
Question: how can I isolate just the overlapping area into a separate shape and calculate its area?
I have looked at STIntersects, but that seems to only be useful for determining if the shapes intersect, and not for finding the actual intersection. I understand that once I have the intersection, finding its area is trivial with STArea.
Actually, after discovering the STIntersection function, I think this works:
WITH cte_school1
AS (SELECT b.*
FROM dbo.BndPrimarySchoolZone b
WHERE b.ncessch = 250315000417),
cte_school2
AS (SELECT b.*
FROM dbo.BndPrimarySchoolZone b
WHERE b.ncessch = 250315000421)
SELECT s1.Shape.STIntersection(s2.Shape),
s1.Shape.STIntersection(s2.Shape).STArea()
FROM cte_school1 s1
JOIN cte_school2 s2
ON s1.Shape.STIntersects(s2.Shape) = 1;
If there is a better way to do it, please post in comments.

SQL Server function/stored proc to return a set of aggregations based on a set of points

I have a table of x,y coordinates - let's say they represent map locations of cell phone pings. The table also has a personID to represent the owner of the phone.
I also have a function (which could be changed to something else to suit this solution) that accepts a set of points as a table variable and generates some aggregations of them (average and stdev in both directions). The example shows the table type and a function that could do this.
create type tblCoordinate AS table (x float, y float)
go
create function PointsAggregations(#pts tblCoordinate readonly)
returns table as
return
select avg(x) AvgX, avg(y) avgY, stdev(x) stdevx, stdev(y) stdevy
from #pts
Question is how would I structure this so I could get a table of these aggregations by PersonID. That is, I would like to call this function and pass it the unique set of points for every PersonID in the table, and end up with a table of structure.
PersonID, avgX, avgY, stdevX, stdevY.
Feels like a weird reverse-cross apply kinda thing, but I can't quite figure out if it's possible. Note: the actual problem is much more complicated than the simple aggregations shown here - I am trying to encapsulate an algorithm that creates a "confidence ellipse" of the points - lots of math involved that aren't applicable to the posted question - so simply performing the aggregations within a single query and getting rid of the function isn't a solution.

How to speed up query that use postgis extension?

I have the following query that checks whether is point (T.latitude, T.longitude) is inside a POLYGON
query = """
SELECT id
FROM T
WHERE ST_Intersects(ST_Point(T.latitude, T.longitude), 'POLYGON(({points}))')
"""
But it works slow, how can I speed up it if I have the following index:
(latitude, longitude)?
The query is slow because it must compute the formula for every possible pair of points. So it makes the postgress server do a lot of math, and it forces it to scan through your whole location table. How can we optimize this? Maybe we can eliminate the points that are too far north or too far south or too far east or west?
1) Add a geometry column of type Geometry(Point) and fill it:
ALTER TABLE T add COLUMN geom geometry(Point);
UPDATE T SET geom = ST_Point(T.latitude, T.longitude);
2) Create a spatial index:
CREATE INDEX t_gix ON t USING GIST (geom);
3) Use ST_DWithin instead of ST_Intersect:
WHERE ST_DWithin('POLYGON(({points}))', geom, 0)
You want actually find the points which are within a polygon, so ST_DWithin() is what you need. From the documentation:
This function call will automatically include a bounding box
comparison that will make use of any indexes that are available
PS:
If you for some reason cannot make the points 1 and 2, so at least use ST_Dwithin instead of ST_Intersect:
WHERE ST_DWithin('POLYGON(({points}))', ST_Point(T.latitude, T.longitude), 0)
The last parameter is the tolerance.
You can easly speed up your spatial queries that adding t1.geom&&t2.geom condition to your scripts
This condition;
required spatial indexies so your spatial columns must have spatial indexies
returns approximate result (but with st_ Operators gives exact result)
Here is a example at my database and query timings;
select p.id,k.id, p.poly&&k.poly as intersects
from parcel p , enterance k
where st_contains(p.poly,k.poly) and p.poly&&k.poly
--without && 10.4 sec
--with && 1.6 sec
select count(*) from parcel --34797
select count(*) from enterance --70715
https://postgis.net/docs/overlaps_geometry_box2df.html

PostGIS geometry database query

I have several tables that contain multipolygons. I need to find points within these polygons that I can use in my java test class. What I have been doing is sending a query to return all the multi polygons, choose a vertex to use as a point, and most times it works.
However these tables represent risk data, 1 in 100, 1 in 200 etc, and so some of the points are shared between tables (the higher risk multi polygons are encapsulated by the lower risk). what query can I use to return a point that will be within 1 multipolygon in 1 table, but not in any others that I specify?
the tables are river_100_1k, river_200_1k, and river_1000_1k
Well you could do a multiple left join:
SELECT a.gid, a.the_geom FROM pointsTable a
LEFT JOIN river_100_1k b
ON ST_Intersects(a.the_geom, b.the_geom)
LEFT JOIN
river_200_1k c
ON NOT ST_Intersects(a.the_geom, c.the_geom) -- Not Intersects
LEFT JOIN
river_1000_1k d
ON NOT ST_Intersects(a.the_geom, d.the_geom) -- Not Intersects
WHERE
AND c.gid IS NULL AND d.gid IS NULL AND b.gid=2 AND c.gid=2 AND d.gid=2 ;
I'm not sure if I understand correctly but this is the path you should take.
Use ST_PointOnSurface(polygon) to get a point within a polygon.

Resources