lower
Range types (including `lower()`) introduced in PostgreSQL 9.2. Multirange variants require PostgreSQL 14+.→ same as range element typeReturns the lower bound of the range. Returns NULL if the range has no lower bound (unbounded).
Signature
lower ( anyrange ) → anyelementParameters
| Parameter | Type | Description |
|---|---|---|
| range | anyrange | Range value to extract lower bound from |
Examples
SELECT lower('[2025-01-01,2025-12-31]'::daterange);2025-01-01SELECT lower('[1,10)'::int4range);1SELECT lower('(,5)'::int4range);NULL (unbounded lower)SELECT id, lower(booking_period) AS check_in FROM room_bookings WHERE lower(booking_period) >= CURRENT_DATE ORDER BY 2;Upcoming check-in dates sorted chronologicallyStoring a range as separate `start_date` and `end_date` columns forces you to write `WHERE start_date <= $ts AND end_date > $ts` everywhere. A range column with a GiST index handles overlap, containment, and adjacency in a single operator (`&&`, `@>`, `-|-`) and the index is used automatically.
✓ Instead: ALTER TABLE bookings ADD COLUMN period daterange GENERATED ALWAYS AS (daterange(start_date, end_date)) STORED; CREATE INDEX ON bookings USING gist(period);
Use `lower_inf(range)` to test if the lower bound is infinite (unbounded) before calling `lower()`. `lower()` returns NULL for unbounded ranges, which can cause unexpected behavior in comparisons.
SELECT CASE WHEN lower_inf(period) THEN 'since forever' ELSE lower(period)::text END AS start FROM subscriptions;Human-readable range start