> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firebolt.io/llms.txt
> Use this file to discover all available pages before exploring further.

> Reference material for ST_CONTAINS function

# ST_CONTAINS

The `ST_CONTAINS` function determines if one `GEOGRAPHY` object fully contains another. Specifically, it checks whether every point in the second `GEOGRAPHY` object (`geo2`) lies within or on the boundary of the first `GEOGRAPHY` object (`geo1`), and the interiors of the two input objects intersect. If `geo1` contains `geo2`, the function returns `TRUE`; otherwise, it returns `FALSE`. This function is commonly used to assess spatial relationships, such as whether a larger geographic area completely includes a smaller one.

If either `geo1` or `geo2` is empty, `ST_CONTAINS` will return `FALSE`.

Before performing the containment check, `geo1` and `geo2` are aligned through a snapping process, ensuring precise calculation. For more details on snapping, refer to the [snapping documentation](/reference-sql/data-types/geography#snapping).

## Interior definition

A notable part of `ST_CONTAINS` is that the interiors of the inputs must intersect. The interior for the different `GEOGRAPHY` shape types is defined as follows:

* Point: The interior of a point consists only of the point itself, and is defined by its location.

* LineString: All vertices and line segments of a LineString are part of the interior, except for the first and the last vertex.
  * If the first and the last vertex are the same point after snapping, then this point is also part of the interior.

  * If the interior passes through the first and last vertex, or just one of them, then it is part of the interior.

* Polygon: Every point within the boundaries, excluding points on the boundaries themselves, is part of the interior.

* MultiPoint, MultiLineString, MultiPolygon, GeometryCollection: Any point that lies within the interior of one of the shapes in the collection is part of the collection's interior.

## Comparison with [ST\_COVERS](/reference-sql/functions-reference/geospatial/st_covers)

`ST_CONTAINS` is similar to `ST_COVERS`, but there is a key distinction: `ST_CONTAINS` returns `FALSE` if all points in `geo2` lie exactly on the boundary of `geo1`, while `ST_COVERS` will return `TRUE` in this case. This behavior arises from an additional requirement in `ST_CONTAINS` that the interiors of the geometries must intersect. If this distinction is not important, use `ST_COVERS`, which is more efficient to compute in Firebolt.

## Syntax

```sql theme={"theme":{"light":"github-light","dark":"github-dark"}}
ST_CONTAINS(<geo1>, <geo2>)
```

## Parameters

| Parameter | Description                                                                   | Supported input types |
| :-------- | :---------------------------------------------------------------------------- | :-------------------- |
| `<geo1>`  | The object being checked to see if it fully contains the second object.       | `GEOGRAPHY`           |
| `<geo2>`  | The object being checked to see if it is fully contained by the first object. | `GEOGRAPHY`           |

## Return Type

`ST_CONTAINS` returns a value of type `BOOLEAN`.

## Example

The following codes example creates a Polygon and a Point around Times Square in New York City from their WKT representations and checks if the Polygon contains the Point:

```sql theme={"theme":{"light":"github-light","dark":"github-dark"}}
SELECT ST_CONTAINS(
ST_GEOGFROMTEXT('POLYGON((-73.98519512134791 40.75939223091697, -73.98566488210841 40.75807135585606, -73.9856079414103 40.75804080469413, -73.98470163529633 40.75918017383259, -73.98519512134791 40.75939223091697))'),
ST_GEOGFROMTEXT('POINT(-73.98504378555772 40.75894662495352)')
) AS result
```

**Returns**

| result (BOOLEAN) |
| :--------------- |
| t                |

## Example

The following example illustrates the difference between `ST_CONTAINS` and `ST_COVERS`. The Polygon `POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))` covers, but does not contain the LineString `LINESTRING(0 0, 0 0.5)` because it only lies on the Polygon's boundary and does not intersect the interior of the Polygon. The LineString `LINESTRING(0 0, 0 0.5, 0.5 0.5)` only partially lies on the Polygon's boundary but also intersects its interior, so it is covered and contained.

```sql theme={"theme":{"light":"github-light","dark":"github-dark"}}
SELECT 
    polygon, 
    linestring, 
    ST_CONTAINS(
        ST_GEOGFROMTEXT(polygon),
        ST_GEOGFROMTEXT(linestring)
    ) AS contains,
    ST_COVERS(
        ST_GEOGFROMTEXT(polygon),
        ST_GEOGFROMTEXT(linestring)
    ) AS covers
    FROM UNNEST (
        ['POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))','POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'], 
        ['LINESTRING(0 0, 0 0.5)','LINESTRING(0 0, 0 0.5, 0.5 0.5)']
    ) AS shapes(polygon, linestring)
```

**Returns**

| polygon (TEXT)                       | linestring (TEXT)                 | contains (BOOLEAN) | covers (BOOLEAN) |
| :----------------------------------- | :-------------------------------- | :----------------- | :--------------- |
| 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))' | 'LINESTRING(0 0, 0 0.5)'          | f                  | t                |
| 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))' | 'LINESTRING(0 0, 0 0.5, 0.5 0.5)' | t                  | t                |
