Test whether the first geometry completely contains the second geometry.
ST_CONTAINS(geom1, geom2)
## Overview Returns TRUE if every point of geom2 lies in the interior or on the boundary of geom1, and at least one point of geom2 lies in the interior of geom1. In plain terms, geom1 contains geom2 when geom2 fits completely inside geom1. The relationship is directional: ST_CONTAINS(A, B) is not the same as ST_CONTAINS(B, A). ST_CONTAINS is the primary predicate for point-in-polygon queries, geofencing, and region membership joins. It is the mirror of ST_WITHIN: ST_CONTAINS(A, B) is equivalent to ST_WITHIN(B, A), with the arguments swapped. ## When to use ST_CONTAINS vs. alternatives - **ST_CONTAINS** (this function): "does the outer shape contain the inner shape?". Use when the polygon is on the left of the predicate and the candidate point or small shape is on the right. - **ST_WITHIN**: the same relationship with swapped arguments. Use when the candidate is on the left ("is this point within any zone?"). - **ST_DISTANCE / ST_DISTANCE_HAVERSINE**: proximity, not containment. Use when you care about a buffered radius rather than strict membership. - **Bounding-box pre-filter**: for large tables, pre-filter with a cheap bbox check before calling ST_CONTAINS, or use H3 cell prefiltering for geographic data. ## Behavior - Returns BOOLEAN. - Implemented with a ray-casting point-in-polygon algorithm for the POINT-in-POLYGON case. Points that sit exactly on an edge may return either TRUE or FALSE depending on floating-point rounding; do not rely on boundary behavior. - Both geometries are treated as planar. The function does not apply Earth curvature. For small regions the planar approximation is fine; for continental-scale polygons reproject into an equal-area CRS first. - Argument order matters. ST_CONTAINS(polygon, point) 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, but the most common pairing is (POLYGON, POINT) or (MULTIPOLYGON, POINT). ## Input format - Accepts any GEOMETRY value built by ST_GEOM_FROM_TEXT, ST_MAKE_POINT, or derived from other ST_ functions. - Polygons must be closed (first and last vertex identical); ST_GEOM_FROM_TEXT enforces this during parsing. - For MULTIPOLYGON inputs, geom2 is contained if it lies entirely within any single polygon of the multi; splitting across polygons is not considered containment. ## Compatibility - Follows the OGC Simple Features definition of the contains predicate. - Matches the semantics of ST_CONTAINS in most SQL-based geospatial engines for planar inputs.
| Name | Type | Description |
|---|---|---|
geom1 | Specifies the outer (containing) geometry. Typically a POLYGON or MULTIPOLYGON used as a region, fence, or envelope. | |
geom2 | Specifies the inner (candidate) geometry. Any geometry type is accepted, but the semantics are most intuitive when geom2 is a POINT, LINESTRING, or smaller POLYGON. |
-- Returns TRUE because the point lies strictly inside the square.
SELECT ST_CONTAINS(
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'),
ST_MAKE_POINT(5, 5)
) AS contained;
-- Returns FALSE; the point is outside the square.
SELECT ST_CONTAINS(
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'),
ST_MAKE_POINT(15, 5)
) AS contained;
-- Return customers whose home coordinates fall inside a service-area polygon.
SELECT customer_id, name
FROM crm.catalog.customers c
JOIN gis.catalog.service_zones z ON z.zone_id = 'LDN-CENTRAL'
WHERE ST_CONTAINS(z.zone_geom, ST_MAKE_POINT(c.longitude, c.latitude));
-- Aggregate events into the regions that contain them.
SELECT r.region_name, COUNT(e.event_id) AS event_count
FROM gis.catalog.regions r
JOIN events.catalog.pings e
ON ST_CONTAINS(r.boundary, ST_MAKE_POINT(e.lng, e.lat))
GROUP BY r.region_name;
-- ST_CONTAINS(a, b) is equivalent to ST_WITHIN(b, a). Arguments are swapped.
SELECT
ST_CONTAINS(poly, pt) AS contains_result,
ST_WITHIN(pt, poly) AS within_result
FROM (SELECT
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))') AS poly,
ST_MAKE_POINT(5, 5) AS pt) t;
-- Boundary behavior is implementation-defined; ray-casting implementations typically return FALSE.
SELECT ST_CONTAINS(
ST_GEOM_FROM_TEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'),
ST_MAKE_POINT(0, 5)
) AS contained;