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

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

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

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

Оператор

Описание

Пример(ы)

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.56. Мультидиапазонные операторы

Оператор

Описание

Пример(ы)

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.54 перечислены функции, предназначенные для работы с диапазонными типами. Функции, предназначенные для использования с мультидиапазонными типами, приведены в Таблице 9.58.

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

Функция

Описание

Пример(ы)

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

У диапазона нет нижней границы? (При указании нижней границы -Infinity возвращается false.)

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

upper_inf ( anyrange ) → boolean

У диапазона нет верхней границы? (При указании верхней границы Infinity возвращается false.)

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

range_merge ( anyrange, anyrange ) → anyrange

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

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


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

Функция

Описание

Пример(ы)

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

У мультидиапазона нет нижней границы? (При указании нижней границы -Infinity возвращается false.)

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

upper_inf ( anymultirange ) → boolean

У мультидиапазона нет верхней границы? (При указании верхней границы Infinity возвращается false.)

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.