Test whether the first geometry lies completely inside the second geometry.
ST_WITHIN(geom1, geom2)
## Overview Returns TRUE if every point of geom1 lies in the interior or on the boundary of geom2, and at least one point of geom1 lies in the interior of geom2. In plain terms, geom1 is within geom2 when geom1 fits completely inside geom2. ST_WITHIN is the mirror of ST_CONTAINS. The identity ST_WITHIN(A, B) is equivalent to ST_CONTAINS(B, A), with the arguments swapped. ST_WITHIN usually reads naturally when the candidate geometry is the one of primary interest ("is this point within any zone?"), while ST_CONTAINS reads naturally when the region is the subject ("does this zone contain any customers?"). ## When to use ST_WITHIN vs. alternatives - **ST_WITHIN** (this function): "does the inner shape fit inside the outer shape?". Use when the candidate is on the left. - **ST_CONTAINS**: the same relationship with swapped arguments. Use when the region is on the left. - **ST_DISTANCE / ST_DISTANCE_HAVERSINE**: proximity, not containment. Use for buffered radius membership instead of strict geometric inclusion. - **Bounding-box pre-filter**: for large tables, pre-filter with a cheap bbox check before calling ST_WITHIN, or use H3 cell prefiltering for geographic data. ## Behavior - Returns BOOLEAN. - Implemented as a ray-casting point-in-polygon test for the POINT-in-POLYGON case. Boundary points have implementation-defined behavior; do not rely on a specific answer for a point that sits exactly on an edge. - Both geometries are treated as planar. For continental-scale polygons reproject into an equal-area CRS before calling. - Argument order matters. ST_WITHIN(point, polygon) is the typical form; reversing the arguments almost always returns FALSE. - Returns NULL if either argument is NULL. - Self-intersecting or otherwise invalid geometries produce implementation-defined results; validate on ingest when the source is untrusted. - Works on any combination of geometry types. The most common pairings are (POINT, POLYGON) and (POINT, MULTIPOLYGON). ## Input format - Accepts any GEOMETRY value built with ST_GEOM_FROM_TEXT, ST_MAKE_POINT, or other ST_ functions. - Polygons must be closed; ST_GEOM_FROM_TEXT enforces this during parsing. - For MULTIPOLYGON outer geometries, geom1 is within if it lies entirely inside any single component polygon; splitting across components is not considered containment. ## Compatibility - Follows the OGC Simple Features definition of the within predicate. - Matches the semantics of ST_WITHIN in most SQL-based geospatial engines for planar inputs.
| Name | Type | Description |
|---|---|---|
geom1 | Specifies the inner (candidate) geometry. Typically a POINT, LINESTRING, or small POLYGON being tested for membership. | |
geom2 | Specifies the outer (containing) geometry. Typically a POLYGON or MULTIPOLYGON representing a region, fence, or envelope. |
-- Returns TRUE; the point lies strictly inside the square.
SELECT ST_WITHIN(
ST_MAKE_POINT(5, 5),
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))')
) AS within;
-- Returns FALSE; the point is outside the square.
SELECT ST_WITHIN(
ST_MAKE_POINT(15, 5),
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))')
) AS within;
-- Candidate on the left, zone on the right, opposite of ST_CONTAINS.
SELECT c.customer_id, c.name
FROM crm.catalog.customers c
JOIN gis.catalog.service_zones z ON z.zone_id = 'LDN-CENTRAL'
WHERE ST_WITHIN(ST_MAKE_POINT(c.longitude, c.latitude), z.zone_geom);
-- For each event, pick the first region that contains it.
SELECT e.event_id, MIN(r.region_name) AS region
FROM events.catalog.pings e
JOIN gis.catalog.regions r
ON ST_WITHIN(ST_MAKE_POINT(e.lng, e.lat), r.boundary)
GROUP BY e.event_id;
-- ST_WITHIN(a, b) and ST_CONTAINS(b, a) return the same result.
SELECT
ST_WITHIN(pt, poly) AS within_result,
ST_CONTAINS(poly, pt) AS contains_result
FROM (SELECT
ST_MAKE_POINT(5, 5) AS pt,
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))') AS poly) t;
-- A point that sits exactly on an edge may return TRUE or FALSE depending on rounding.
SELECT ST_WITHIN(
ST_MAKE_POINT(0, 5),
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))')
) AS within;