Functions / PostGIS / ST_Within
PostGISSpatial Relationships

ST_Within

What is ST_Within?

ST_Within is a PostGIS spatial predicate that returns true when geometry A lies completely inside geometry B. It is the inverse of ST_Contains: ST_Within(A, B) is equivalent to ST_Contains(B, A).

SQL
ST_Within(geometry geomA, geometry geomB)boolean

The DE-9IM pattern is T*F**F*** — A's interior must intersect B's interior, and no part of A may fall in B's exterior.

When would you use ST_Within?

Use ST_Within when you want to check that a feature is strictly inside another — all sensors inside a country, all buildings inside a zone, all tracks inside a study area. The common idiom "find all X in Y" maps directly onto ST_Within(x.geom, y.geom).

SQL
1SELECT s.id
2FROM sensors s
3WHERE ST_Within(s.geom, (SELECT geom FROM zones WHERE name = 'Zone A'));

FAQs

What happens for points on the boundary?

ST_Within excludes points that sit exactly on B's boundary — A's interior must intersect B's interior, so a point on the edge is not within. If you want boundary-inclusive semantics, use ST_CoveredBy(A, B) or equivalently ST_Covers(B, A).

Does ST_Within use a spatial index?

Yes. The planner applies the bounding-box operator @ (A's bbox is contained in B's bbox) against the GiST index before running the exact predicate. This makes ST_Within efficient even for joins between millions of points and thousands of polygons.

How is ST_Within different from ST_ContainsProperly?

ST_Within(A, B) is the inverse of ST_Contains(B, A). ST_ContainsProperly(B, A) is stricter than ST_Contains — it forbids any contact between A and B's boundary. If you want "strictly in the interior with no boundary contact", use ST_ContainsProperly(outer, inner).

Is ST_Within OGC-standard?

Yes, ST_Within is part of the OGC Simple Features for SQL specification. You can rely on it being present in any standards-compliant spatial database, which makes it a good default for portable queries.