9.20. Диапазонные/мультидиапазонные функции и операторы

Диапазонные типы данных рассматриваются в Разделе 8.17.

В Таблице 9.53 показаны имеющиеся специальные операторы для диапазонных типов, а в Таблице 9.54 — для мультидиапазонных типов. Кроме них для диапазонов и мультидиапазонов определены обычные операторы сравнения, показанные в Таблице 9.1. Операторы сравнения сначала сравнивают нижние границы диапазонов, и только если они равны, сравнивают верхние границы. Операторы сравнения мультидиапазонов сравнивают каждый диапазон, пока не найдут неравенство. Такие операторы сравнения обычно не помогают получить полезный в целом вариант сортировки, но позволяют строить по диапазонам уникальные индексы.

Таблица 9.53. Диапазонные операторы

Оператор

Описание

Пример(ы)

anyrange @> anyrangeboolean

Первый диапазон содержит второй?

int4range(2,4) @> int4range(2,3)t

anyrange @> anyelementboolean

Диапазон содержит заданный элемент?

'[2011-01-01,2011-03-01)'::tsrange @> '2011-01-10'::timestampt

anyrange <@ anyrangeboolean

Первый диапазон содержится во втором?

int4range(2,4) <@ int4range(1,7)t

anyelement <@ anyrangeboolean

Заданный элемент содержится в диапазоне?

42 <@ int4range(1,7)f

anyrange && anyrangeboolean

Диапазоны пересекаются (у них есть общие элементы)?

int8range(3,7) && int8range(4,12)t

anyrange << anyrangeboolean

Первый диапазон располагается строго слева от второго?

int8range(1,10) << int8range(100,110)t

anyrange >> anyrangeboolean

Первый диапазон располагается строго справа от второго?

int8range(50,60) >> int8range(20,30)t

anyrange &< anyrangeboolean

Первый диапазон не простирается правее второго?

int8range(1,20) &< int8range(18,20)t

anyrange &> anyrangeboolean

Первый диапазон не простирается левее второго?

int8range(7,20) &> int8range(5,10)t

anyrange -|- anyrangeboolean

Диапазоны примыкают друг к другу?

numrange(1.1,2.2) -|- numrange(2.2,3.3)t

anyrange + anyrangeanyrange

Вычисляет объединение диапазонов. Диапазоны должны пересекаться или касаться друг друга, чтобы их объединением был один диапазон (но см. range_merge()).

numrange(5,15) + numrange(10,20)[5,20)

anyrange * anyrangeanyrange

Вычисляет пересечение диапазонов.

int8range(5,15) * int8range(10,20)[10,15)

anyrange - anyrangeanyrange

Вычисляет разность диапазонов. При этом второй диапазон, если он содержится в первом, должен располагаться так, чтобы в результате его вычитания получался один диапазон.

int8range(5,15) - int8range(10,20)[5,10)


Таблица 9.54. Мультидиапазонные операторы

Оператор

Описание

Пример(ы)

anymultirange @> anymultirangeboolean

Первый мультидиапазон содержит второй?

'{[2,4)}'::int4multirange @> '{[2,3)}'::int4multiranget

anymultirange @> anyrangeboolean

Мультидиапазон содержит заданный диапазон?

'{[2,4)}'::int4multirange @> int4range(2,3)t

anymultirange @> anyelementboolean

Мультидиапазон содержит заданный элемент?

'{[2011-01-01,2011-03-01)}'::tsmultirange @> '2011-01-10'::timestampt

anyrange @> anymultirangeboolean

Диапазон содержит заданный мультидиапазон?

'[2,4)'::int4range @> '{[2,3)}'::int4multiranget

anymultirange <@ anymultirangeboolean

Первый мультидиапазон содержится во втором?

'{[2,4)}'::int4multirange <@ '{[1,7)}'::int4multiranget

anymultirange <@ anyrangeboolean

Мультидиапазон содержится в диапазоне?

'{[2,4)}'::int4multirange <@ int4range(1,7)t

anyrange <@ anymultirangeboolean

Диапазон содержится в мультидиапазоне?

int4range(2,4) <@ '{[1,7)}'::int4multiranget

anyelement <@ anymultirangeboolean

Заданный элемент содержится в мультидиапазоне?

4 <@ '{[1,7)}'::int4multiranget

anymultirange && anymultirangeboolean

Мультидиапазоны пересекаются (у них есть общие элементы)?

'{[3,7)}'::int8multirange && '{[4,12)}'::int8multiranget

anymultirange && anyrangeboolean

Мультидиапазон пересекает заданный диапазон?

'{[3,7)}'::int8multirange && int8range(4,12)t

anyrange && anymultirangeboolean

Диапазон пересекает заданный мультидиапазон?

int8range(3,7) && '{[4,12)}'::int8multiranget

anymultirange << anymultirangeboolean

Первый мультидиапазон располагается строго слева от второго?

'{[1,10)}'::int8multirange << '{[100,110)}'::int8multiranget

anymultirange << anyrangeboolean

Мультидиапазон располагается строго слева от заданного диапазона?

'{[1,10)}'::int8multirange << int8range(100,110)t

anyrange << anymultirangeboolean

Диапазон располагается строго слева от заданного мультидиапазона?

int8range(1,10) << '{[100,110)}'::int8multiranget

anymultirange >> anymultirangeboolean

Первый мультидиапазон располагается строго справа от второго?

'{[50,60)}'::int8multirange >> '{[20,30)}'::int8multiranget

anymultirange >> anyrangeboolean

Мультидиапазон располагается строго справа от заданного диапазона?

'{[50,60)}'::int8multirange >> int8range(20,30)t

anyrange >> anymultirangeboolean

Диапазон располагается строго справа от заданного мультидиапазона?

int8range(50,60) >> '{[20,30)}'::int8multiranget

anymultirange &< anymultirangeboolean

Первый мультидиапазон не простирается правее второго?

'{[1,20)}'::int8multirange &< '{[18,20)}'::int8multiranget

anymultirange &< anyrangeboolean

Мультидиапазон не простирается правее заданного диапазона?

'{[1,20)}'::int8multirange &< int8range(18,20)t

anyrange &< anymultirangeboolean

Диапазон не простирается правее заданного мультидиапазона?

int8range(1,20) &< '{[18,20)}'::int8multiranget

anymultirange &> anymultirangeboolean

Первый мультидиапазон не простирается левее второго?

'{[7,20)}'::int8multirange &> '{[5,10)}'::int8multiranget

anymultirange &> anyrangeboolean

Мультидиапазон не простирается левее заданного диапазона?

'{[7,20)}'::int8multirange &> int8range(5,10)t

anyrange &> anymultirangeboolean

Диапазон не простирается левее заданного мультидиапазона?

int8range(7,20) &> '{[5,10)}'::int8multiranget

anymultirange -|- anymultirangeboolean

Мультидиапазоны примыкают друг к другу?

'{[1.1,2.2)}'::nummultirange -|- '{[2.2,3.3)}'::nummultiranget

anymultirange -|- anyrangeboolean

Мультидиапазон примыкает к заданному диапазону?

'{[1.1,2.2)}'::nummultirange -|- numrange(2.2,3.3)t

anyrange -|- anymultirangeboolean

Диапазон примыкает к заданному мультидиапазону?

numrange(1.1,2.2) -|- '{[2.2,3.3)}'::nummultiranget

anymultirange + anymultirangeanymultirange

Вычисляет объединение мультидиапазонов. Мультидиапазоны могут не пересекаться и не примыкать друг к другу.

'{[5,10)}'::nummultirange + '{[15,20)}'::nummultirange{[5,10), [15,20)}

anymultirange * anymultirangeanymultirange

Вычисляет пересечение мультидиапазонов.

'{[5,15)}'::int8multirange * '{[10,20)}'::int8multirange{[10,15)}

anymultirange - anymultirangeanymultirange

Вычисляет разность мультидиапазонов.

'{[5,20)}'::int8multirange - '{[10,15)}'::int8multirange{[5,10), [15,20)}


Операторы слева/справа/примыкает всегда возвращают false, если один из диапазонов или мультидиапазонов пуст; то есть, считается, что пустой диапазон находится не слева и не справа от какого-либо другого диапазона.

В других случаях пустые диапазоны и мультидиапазоны рассматриваются как нулевой элемент: всё, что объединяется с пустым значением, остаётся неизменным. Все, от чего отнимается пустое значение, остаётся неизменным. Пустой мультидиапазон обладает теми же свойствами, что и пустой диапазон. Каждый диапазон содержит пустой диапазон. Каждый мультидиапазон содержит сколько угодно пустых диапазонов.

При вычислении операторов объединения и вычитания диапазонов возникнет ошибка, если в результате получатся два непересекающихся поддиапазона, поскольку такой результат нельзя представить в виде диапазона. Существуют отдельные операторы для объединения и вычитания, которые принимают мультидиапазонные параметры и возвращают мультидиапазон, и они не вызовут ошибку, даже если их аргументы не пересекаются. Поэтому, если вы хотите избежать ошибок при объединении или вычитании диапазонов, когда могут получиться непересекающиеся поддиапазоны, сначала преобразуйте входные диапазоны в мультидиапазоны.

В Таблице 9.52 перечислены функции, предназначенные для работы с диапазонными типами. Функции, предназначенные для использования с мультидиапазонными типами, приведены в Таблице 9.56.

Таблица 9.55. Диапазонные функции

Функция

Описание

Пример(ы)

lower ( anyrange ) → anyelement

Выдаёт нижнюю границу диапазона (NULL, если диапазон пуст или нижняя граница не является конечной).

lower(numrange(1.1, 2.2))1.1

upper ( anyrange ) → anyelement

Выдаёт верхнюю границу диапазона (NULL, если диапазон пуст или верхняя граница не является конечной).

upper(numrange(1.1, 2.2))2.2

isempty ( anyrange ) → boolean

Диапазон пуст?

isempty(numrange(1.1,2.2))f

lower_inc ( anyrange ) → boolean

Нижняя граница диапазона включается в него?

lower_inc(numrange(1.1, 2.2))t

upper_inc ( anyrange ) → boolean

Верхняя граница диапазона включается в него?

upper_inc(numrange(1.1, 2.2))f

lower_inf ( anyrange ) → boolean

Нижняя граница диапазона бесконечна?

lower_inf('(,)'::daterange)t

upper_inf ( anyrange ) → boolean

Верхняя граница диапазона бесконечна?

upper_inf('(,)'::daterange)t

range_merge ( anyrange, anyrange ) → anyrange

Вычисляет наименьший диапазон, включающий оба заданных диапазона.

range_merge('[1,2)'::int4range, '[3,4)'::int4range)[1,4)


Таблица 9.56. Мультидиапазонные функции

Функция

Описание

Пример(ы)

lower ( anymultirange ) → anyelement

Выдаёт нижнюю границу мультидиапазона (NULL, если мультидиапазон пуст или нижняя граница не является конечной).

lower('{[1.1,2.2)}'::nummultirange)1.1

upper ( anymultirange ) → anyelement

Выдаёт верхнюю границу мультидиапазона (NULL, если мультидиапазон пуст или верхняя граница не является конечной).

upper('{[1.1,2.2)}'::nummultirange)2.2

isempty ( anymultirange ) → boolean

Мультидиапазон пуст?

isempty('{[1.1,2.2)}'::nummultirange)f

lower_inc ( anymultirange ) → boolean

Нижняя граница мультидиапазона включается в него?

lower_inc('{[1.1,2.2)}'::nummultirange)t

upper_inc ( anymultirange ) → boolean

Верхняя граница мультидиапазона включается в него?

upper_inc('{[1.1,2.2)}'::nummultirange)f

lower_inf ( anymultirange ) → boolean

Нижняя граница мультидиапазона бесконечна?

lower_inf('{(,)}'::datemultirange)t

upper_inf ( anymultirange ) → boolean

Верхняя граница мультидиапазона бесконечна?

upper_inf('{(,)}'::datemultirange)t

range_merge ( anymultirange ) → anyrange

Вычисляет наименьший диапазон, включающий весь заданный мультидиапазон.

range_merge('{[1,2), [3,4)}'::int4multirange)[1,4)

multirange ( anyrange ) → anymultirange

Возвращает мультидиапазон, содержащий только заданный диапазон.

multirange('[1,2)'::int4range){[1,2)}

unnest ( anymultirange ) → set of anyrange

Разворачивает мультидиапазон в набор диапазонов. Диапазоны прочитываются в порядке хранения (восходящем).

unnest('{[1,2), [3,4)}'::int4multirange)

 [1,2)
 [3,4)


Если функциям lower_inc, upper_inc, lower_inf, upper_inf передаётся пустой диапазон или мультидиапазон, они возвращают false.

9.20. Range/Multirange Functions and Operators

See Section 8.17 for an overview of range types.

Table 9.53 shows the specialized operators available for range types. Table 9.54 shows the specialized operators available for multirange types. In addition to those, the usual comparison operators shown in Table 9.1 are available for range and multirange types. The comparison operators order first by the range lower bounds, and only if those are equal do they compare the upper bounds. The multirange operators compare each range until one is unequal. This does not usually result in a useful overall ordering, but the operators are provided to allow unique indexes to be constructed on ranges.

Table 9.53. Range Operators

Operator

Description

Example(s)

anyrange @> anyrangeboolean

Does the first range contain the second?

int4range(2,4) @> int4range(2,3)t

anyrange @> anyelementboolean

Does the range contain the element?

'[2011-01-01,2011-03-01)'::tsrange @> '2011-01-10'::timestampt

anyrange <@ anyrangeboolean

Is the first range contained by the second?

int4range(2,4) <@ int4range(1,7)t

anyelement <@ anyrangeboolean

Is the element contained in the range?

42 <@ int4range(1,7)f

anyrange && anyrangeboolean

Do the ranges overlap, that is, have any elements in common?

int8range(3,7) && int8range(4,12)t

anyrange << anyrangeboolean

Is the first range strictly left of the second?

int8range(1,10) << int8range(100,110)t

anyrange >> anyrangeboolean

Is the first range strictly right of the second?

int8range(50,60) >> int8range(20,30)t

anyrange &< anyrangeboolean

Does the first range not extend to the right of the second?

int8range(1,20) &< int8range(18,20)t

anyrange &> anyrangeboolean

Does the first range not extend to the left of the second?

int8range(7,20) &> int8range(5,10)t

anyrange -|- anyrangeboolean

Are the ranges adjacent?

numrange(1.1,2.2) -|- numrange(2.2,3.3)t

anyrange + anyrangeanyrange

Computes the union of the ranges. The ranges must overlap or be adjacent, so that the union is a single range (but see range_merge()).

numrange(5,15) + numrange(10,20)[5,20)

anyrange * anyrangeanyrange

Computes the intersection of the ranges.

int8range(5,15) * int8range(10,20)[10,15)

anyrange - anyrangeanyrange

Computes the difference of the ranges. The second range must not be contained in the first in such a way that the difference would not be a single range.

int8range(5,15) - int8range(10,20)[5,10)


Table 9.54. Multirange Operators

Operator

Description

Example(s)

anymultirange @> anymultirangeboolean

Does the first multirange contain the second?

'{[2,4)}'::int4multirange @> '{[2,3)}'::int4multiranget

anymultirange @> anyrangeboolean

Does the multirange contain the range?

'{[2,4)}'::int4multirange @> int4range(2,3)t

anymultirange @> anyelementboolean

Does the multirange contain the element?

'{[2011-01-01,2011-03-01)}'::tsmultirange @> '2011-01-10'::timestampt

anyrange @> anymultirangeboolean

Does the range contain the multirange?

'[2,4)'::int4range @> '{[2,3)}'::int4multiranget

anymultirange <@ anymultirangeboolean

Is the first multirange contained by the second?

'{[2,4)}'::int4multirange <@ '{[1,7)}'::int4multiranget

anymultirange <@ anyrangeboolean

Is the multirange contained by the range?

'{[2,4)}'::int4multirange <@ int4range(1,7)t

anyrange <@ anymultirangeboolean

Is the range contained by the multirange?

int4range(2,4) <@ '{[1,7)}'::int4multiranget

anyelement <@ anymultirangeboolean

Is the element contained by the multirange?

4 <@ '{[1,7)}'::int4multiranget

anymultirange && anymultirangeboolean

Do the multiranges overlap, that is, have any elements in common?

'{[3,7)}'::int8multirange && '{[4,12)}'::int8multiranget

anymultirange && anyrangeboolean

Does the multirange overlap the range?

'{[3,7)}'::int8multirange && int8range(4,12)t

anyrange && anymultirangeboolean

Does the range overlap the multirange?

int8range(3,7) && '{[4,12)}'::int8multiranget

anymultirange << anymultirangeboolean

Is the first multirange strictly left of the second?

'{[1,10)}'::int8multirange << '{[100,110)}'::int8multiranget

anymultirange << anyrangeboolean

Is the multirange strictly left of the range?

'{[1,10)}'::int8multirange << int8range(100,110)t

anyrange << anymultirangeboolean

Is the range strictly left of the multirange?

int8range(1,10) << '{[100,110)}'::int8multiranget

anymultirange >> anymultirangeboolean

Is the first multirange strictly right of the second?

'{[50,60)}'::int8multirange >> '{[20,30)}'::int8multiranget

anymultirange >> anyrangeboolean

Is the multirange strictly right of the range?

'{[50,60)}'::int8multirange >> int8range(20,30)t

anyrange >> anymultirangeboolean

Is the range strictly right of the multirange?

int8range(50,60) >> '{[20,30)}'::int8multiranget

anymultirange &< anymultirangeboolean

Does the first multirange not extend to the right of the second?

'{[1,20)}'::int8multirange &< '{[18,20)}'::int8multiranget

anymultirange &< anyrangeboolean

Does the multirange not extend to the right of the range?

'{[1,20)}'::int8multirange &< int8range(18,20)t

anyrange &< anymultirangeboolean

Does the range not extend to the right of the multirange?

int8range(1,20) &< '{[18,20)}'::int8multiranget

anymultirange &> anymultirangeboolean

Does the first multirange not extend to the left of the second?

'{[7,20)}'::int8multirange &> '{[5,10)}'::int8multiranget

anymultirange &> anyrangeboolean

Does the multirange not extend to the left of the range?

'{[7,20)}'::int8multirange &> int8range(5,10)t

anyrange &> anymultirangeboolean

Does the range not extend to the left of the multirange?

int8range(7,20) &> '{[5,10)}'::int8multiranget

anymultirange -|- anymultirangeboolean

Are the multiranges adjacent?

'{[1.1,2.2)}'::nummultirange -|- '{[2.2,3.3)}'::nummultiranget

anymultirange -|- anyrangeboolean

Is the multirange adjacent to the range?

'{[1.1,2.2)}'::nummultirange -|- numrange(2.2,3.3)t

anyrange -|- anymultirangeboolean

Is the range adjacent to the multirange?

numrange(1.1,2.2) -|- '{[2.2,3.3)}'::nummultiranget

anymultirange + anymultirangeanymultirange

Computes the union of the multiranges. The multiranges need not overlap or be adjacent.

'{[5,10)}'::nummultirange + '{[15,20)}'::nummultirange{[5,10), [15,20)}

anymultirange * anymultirangeanymultirange

Computes the intersection of the multiranges.

'{[5,15)}'::int8multirange * '{[10,20)}'::int8multirange{[10,15)}

anymultirange - anymultirangeanymultirange

Computes the difference of the multiranges.

'{[5,20)}'::int8multirange - '{[10,15)}'::int8multirange{[5,10), [15,20)}


The left-of/right-of/adjacent operators always return false when an empty range or multirange is involved; that is, an empty range is not considered to be either before or after any other range.

Elsewhere empty ranges and multiranges are treated as the additive identity: anything unioned with an empty value is itself. Anything minus an empty value is itself. An empty multirange has exactly the same points as an empty range. Every range contains the empty range. Every multirange contains as many empty ranges as you like.

The range union and difference operators will fail if the resulting range would need to contain two disjoint sub-ranges, as such a range cannot be represented. There are separate operators for union and difference that take multirange parameters and return a multirange, and they do not fail even if their arguments are disjoint. So if you need a union or difference operation for ranges that may be disjoint, you can avoid errors by first casting your ranges to multiranges.

Table 9.55 shows the functions available for use with range types. Table 9.56 shows the functions available for use with multirange types.

Table 9.55. Range Functions

Function

Description

Example(s)

lower ( anyrange ) → anyelement

Extracts the lower bound of the range (NULL if the range is empty or the lower bound is infinite).

lower(numrange(1.1,2.2))1.1

upper ( anyrange ) → anyelement

Extracts the upper bound of the range (NULL if the range is empty or the upper bound is infinite).

upper(numrange(1.1,2.2))2.2

isempty ( anyrange ) → boolean

Is the range empty?

isempty(numrange(1.1,2.2))f

lower_inc ( anyrange ) → boolean

Is the range's lower bound inclusive?

lower_inc(numrange(1.1,2.2))t

upper_inc ( anyrange ) → boolean

Is the range's upper bound inclusive?

upper_inc(numrange(1.1,2.2))f

lower_inf ( anyrange ) → boolean

Is the range's lower bound infinite?

lower_inf('(,)'::daterange)t

upper_inf ( anyrange ) → boolean

Is the range's upper bound infinite?

upper_inf('(,)'::daterange)t

range_merge ( anyrange, anyrange ) → anyrange

Computes the smallest range that includes both of the given ranges.

range_merge('[1,2)'::int4range, '[3,4)'::int4range)[1,4)


Table 9.56. Multirange Functions

Function

Description

Example(s)

lower ( anymultirange ) → anyelement

Extracts the lower bound of the multirange (NULL if the multirange is empty or the lower bound is infinite).

lower('{[1.1,2.2)}'::nummultirange)1.1

upper ( anymultirange ) → anyelement

Extracts the upper bound of the multirange (NULL if the multirange is empty or the upper bound is infinite).

upper('{[1.1,2.2)}'::nummultirange)2.2

isempty ( anymultirange ) → boolean

Is the multirange empty?

isempty('{[1.1,2.2)}'::nummultirange)f

lower_inc ( anymultirange ) → boolean

Is the multirange's lower bound inclusive?

lower_inc('{[1.1,2.2)}'::nummultirange)t

upper_inc ( anymultirange ) → boolean

Is the multirange's upper bound inclusive?

upper_inc('{[1.1,2.2)}'::nummultirange)f

lower_inf ( anymultirange ) → boolean

Is the multirange's lower bound infinite?

lower_inf('{(,)}'::datemultirange)t

upper_inf ( anymultirange ) → boolean

Is the multirange's upper bound infinite?

upper_inf('{(,)}'::datemultirange)t

range_merge ( anymultirange ) → anyrange

Computes the smallest range that includes the entire multirange.

range_merge('{[1,2), [3,4)}'::int4multirange)[1,4)

multirange ( anyrange ) → anymultirange

Returns a multirange containing just the given range.

multirange('[1,2)'::int4range){[1,2)}

unnest ( anymultirange ) → setof anyrange

Expands a multirange into a set of ranges. The ranges are read out in storage order (ascending).

unnest('{[1,2), [3,4)}'::int4multirange)

 [1,2)
 [3,4)


The lower_inc, upper_inc, lower_inf, and upper_inf functions all return false for an empty range or multirange.

FAQ