Tabla de contenidos
Los tipos temporales se basan en cuatro tipos de tiempo: el tipo timestamptz
proporcionado por PostgreSQL y tres nuevos tipos que son period
, timestampset
y periodset
.
El tipo period
es una versión especializada del tipo tstzrange
(abreviatura de rango de marcas de tiempo con zona horaria) proporcionado por PostgreSQL. El tipo period
tiene una funcionalidad similar al tipo tstzrange
pero tiene una implementación más eficiente, en particular es de longitud fija mientras que el tipo tstzrange
es de longitud variable. Además, los períodos vacíos y los límites infinitos no están permitidos en valores de period
, mientras están permitidos en valores de tstzrange
.
Un valor del tipo period
tiene dos límites, el límite inferior y el límite superior, que son valores de timestamptz
. Los límites pueden ser inclusivos o exclusivos. Un límite inclusivo significa que el instante límite está incluido en el período, mientras que un límite exclusivo significa que el instante límite no está incluido en el período. En el formato textual de un valor de period
, los límites inferiores inclusivos y exclusivos están representados, respectivamente, por “[
” y “(
”. Asimismo, los límites superiores inclusivos y exclusivos se representan, respectivamente, por “]
” y “)
”. En un valor de period
, el límite inferior debe ser menor o igual que el límite superior. Un valor de period
con límites iguales e inclusivos se llama período instantáneo y corresponde a un valor de timestamptz
. Ejemplos de valores de period
son como sigue:
SELECT period '[2012-01-01 08:00:00, 2012-01-03 09:30:00)'; -- Período instantáneo SELECT period '[2012-01-01 08:00:00, 2012-01-01 08:00:00]'; -- Período erróneo: límites inválidos SELECT period '[2012-01-01 08:10:00, 2012-01-01 08:00:00]'; -- Período erróneo: período vacío SELECT period '[2012-01-01 08:00:00, 2012-01-01 08:00:00)';
El tipo timestampset
representa un conjunto de valores timestamptz
diferentes. Un valor de timestampset
debe contener al menos un elemento, en cuyo caso corresponde a un valor de timestamptz
. Los elementos que componen un valor de timestampset
deben estar ordenados. Ejemplos de valores de timestampset
son como sigue:
SELECT timestampset '{2012-01-01 08:00:00, 2012-01-03 09:30:00}'; -- Conjunto unitario de marcas de tiempo SELECT timestampset '{2012-01-01 08:00:00}'; -- Conjunto de marcas de tiempo erróneo: elementos desordenados SELECT timestampset '{2012-01-01 08:10:00, 2012-01-01 08:00:00}'; -- Conjunto de marcas de tiempo erróneo: elementos duplicados SELECT timestampset '{2012-01-01 08:00:00, 2012-01-01 08:00:00}';
Finalmente, el tipo periodset
representa un conjunto de valores disjuntos de period
. Un valor de periodset
debe contener al menos un elemento, en cuyo caso corresponde a un valor de period
. Los elementos que componen un valor de periodset
deben estar ordenados. Ejemplos de valores de periodset
son come sigue:
SELECT periodset '{[2012-01-01 08:00:00, 2012-01-01 08:10:00], [2012-01-01 08:20:00, 2012-01-01 08:40:00]}'; -- Conjunto unitario de períodos SELECT periodset '{[2012-01-01 08:00:00, 2012-01-01 08:10:00]}'; -- Conjunto de períodos erróneo: elementos desordenados SELECT periodset '{[2012-01-01 08:20:00, 2012-01-01 08:40:00], [2012-01-01 08:00:00, 2012-01-01 08:10:00]}'; -- Conjunto de períodos erróneo: elementos superpuestos SELECT periodset '{[2012-01-01 08:00:00, 2012-01-01 08:10:00], [2012-01-01 08:05:00, 2012-01-01 08:15:00]}';
Los valores del tipo periodset
son convertidos en forma normal de modo que los valores equivalentes tengan representaciones idénticas. Para ello, los valores de períodos consecutivos que son adyacentes se fusionan cuando es posible. Un ejemplo de transformación a forma normal es el siguiente:
SELECT periodset '{[2012-01-01 08:00:00, 2012-01-01 08:10:00), [2012-01-01 08:10:00, 2012-01-01 08:10:00], (2012-01-01 08:10:00, 2012-01-01 08:20:00]}'; -- "{[2012-01-01 08:00:00+00,2012-01-01 08:20:00+00]}"
Además de los tipos de rango nativos proporcionados por PostgreSQL, MobilityDB define dos tipos de rango adicionales: intrange
(otro nombre para int4range
) y floatrange
.
A continuación presentamos las funciones y operadores para tipos de tiempo y de rango. Estas funciones y operadores son polimórficos, es decir, sus argumentos pueden ser de varios tipos y el tipo de resultado puede depender del tipo de los argumentos. Para expresar esto en la firma de los operadores, utilizamos la siguiente notación:
Un conjunto de tipos como {period,timestampset,periodset}
representa cualquiera de los tipos enumerados,
time
representa cualquier tipo de tiempo, es decir, timestamptz
, period
, timestampset
o periodset
,
number
representa cualquier tipo de número, es decir, integer
o float
,
range
representa cualquier rango de números, es decir, intrange
o floatrange
.
type[]
representa una matriz de type
.
Como ejemplo, la firma del operador contiene (@>
) es como sigue:
{timestampset,period,periodset} @> time
A continuación, por concisión, la parte de tiempo de las marcas de tiempo se omite en los ejemplos. Recuerde que en ese caso PostgreSQL asume el tiempo 00:00:00
.
El tipo period
tiene una función constructora que acepta dos o cuatro argumentos. La forma de dos argumentos construye un punto en forma normal, es decir, con límite inferior inclusivo y límite superior exclusivo. La forma de cuatro argumentos construye un período con límites especificados por el tercer y cuarto argumento, que son valores booleanos que indican, respectivamente, si los límites izquierdo y derecho son inclusivos o no.
Constructor para period
period(timestamptz,timestamptz,left_inc=true,right_inc=false): period
-- Período definido con dos argumentos SELECT period('2012-01-01 08:00:00', '2012-01-03 08:00:00'); -- [2012-01-01 08:00:00+01, 2012-01-03 08:00:00+01) -- Período definido con cuatro argumentos SELECT period('2012-01-01 08:00:00', '2012-01-03 09:30:00', false, true); -- (2012-01-01 08:00:00+01, 2012-01-03 09:30:00+01]
El tipo timestampset
tiene una función constructora que acepta un solo argumento que es una matriz de valores de timestamptz
.
El tipo periodset
tiene una función constructora que acepta un solo argumento que es una matriz de valores de period
.
Los valores de los tipos timestamptz
, tstzrange
o los tipos de tiempo se pueden convertir entre sí utilizando la función CAST
o utilizando la notación ::
.
Convertir un timestamptz
a otro tipo de tiempo
timestamptz::timestampset
timestamptz::period
timestamptz::periodset
SELECT CAST(timestamptz '2012-01-01 08:00:00' AS timestampset); -- "{2012-01-01 08:00:00+01}" SELECT CAST(timestamptz '2012-01-01 08:00:00' AS period); -- "[2012-01-01 08:00:00+01, 2012-01-01 08:00:00+01]" SELECT CAST(timestamptz '2012-01-01 08:00:00' AS periodset); -- "{[2012-01-01 08:00:00+01, 2012-01-01 08:00:00+01]}"
Convertir un timestampset
a un periodset
timestampset::periodset
SELECT CAST(timestampset '{2012-01-01 08:00:00, 2012-01-01 08:15:00, 2012-01-01 08:25:00}' AS periodset); -- "{[2012-01-01 08:00:00+01, 2012-01-01 08:00:00+01], [2012-01-01 08:15:00+01, 2012-01-01 08:15:00+01], [2012-01-01 08:25:00+01, 2012-01-01 08:25:00+01]}"
Convertir un period
a otro tipo de tiempo
period::periodset
period::tstzrange
SELECT period '[2012-01-01 08:00:00, 2012-01-01 08:30:00)'::periodset; -- "{[2012-01-01 08:00:00+01, 2012-01-01 08:30:00+01)}" SELECT period '[2012-01-01 08:00:00, 2012-01-01 08:30:00)'::tstzrange; -- "["2012-01-01 08:00:00+01","2012-01-01 08:30:00+01")"
Convertir un tstzrange
a un period
tstzrange::period
SELECT tstzrange '[2012-01-01 08:00:00, 2012-01-01 08:30:00)'::period; -- "[2012-01-01 08:00:00+01, 2012-01-01 08:30:00+01)"
Obtener el tamaño de la memoria en bytes
memSize({timestampset,periodset}): integer
SELECT memSize(timestampset '{2012-01-01, 2012-01-02, 2012-01-03}'); -- 104 SELECT memSize(periodset '{[2012-01-01, 2012-01-02], [2012-01-03, 2012-01-04], [2012-01-05, 2012-01-06]}'); -- 136
Obtener el límite inferior
lower(period): timestamptz
SELECT lower(period '[2011-01-01, 2011-01-05)'); -- "2011-01-01"
Obtener el límite superior
upper(period): timestamptz
SELECT upper(period '[2011-01-01, 2011-01-05)'); -- "2011-01-05"
¿Es el límite inferior inclusivo?
lower_inc(period): boolean
SELECT lower_inc(period '[2011-01-01, 2011-01-05)'); -- true
¿Es el límite superior inclusivo?
upper_inc(period): boolean
SELECT upper_inc(period '[2011-01-01, 2011-01-05)'); -- false
Obtener el intervalo de tiempo
duration({period,periodset}): interval
SELECT duration(period '[2012-01-01, 2012-01-03)'); -- "2 days" SELECT duration(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-05)}'); -- "3 days"
Obtener el intervalo de tiempo ignorando las posibles brechas de tiempo
timespan({timestampset,period,periodset}): interval
SELECT timespan(timestampset '{2012-01-01, 2012-01-03}'); -- "2 days" SELECT timespan(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-05)}'); -- "4 days"
Obtener el período en el que se define el conjunto de marcas de tiempo o el conjunto de períodos ignorando las posibles brechas de tiempo
period({timestampset,periodset}): period
SELECT period(timestampset '{2012-01-01, 2012-01-03, 2012-01-05}'); -- "[2012-01-01, 2012-01-05]" SELECT period(periodset '{[2012-01-01, 2012-01-02), [2012-01-03, 2012-01-04)}'); -- "[2012-01-01, 2012-01-04)"
Obtener el número de marcas de tiempo diferentes
numTimestamps({timestampset,periodset}): integer
SELECT numTimestamps(timestampset '{2012-01-01, 2012-01-03, 2012-01-04}'); -- 3 SELECT numTimestamps(periodset '{[2012-01-01, 2012-01-03), (2012-01-03, 2012-01-05)}'); -- 3
Obtener la marca de tiempo inicial
startTimestamp({timestampset,periodset}): timestamptz
La función no tiene en cuenta si los límites son inclusivos o no.
SELECT startTimestamp(periodset '{[2012-01-01, 2012-01-03), (2012-01-03, 2012-01-05)}'); -- "2012-01-01"
Obtener la marca de tiempo final
endTimestamp({timestampset,periodset}): timestamptz
La función no tiene en cuenta si los límites son inclusivos o no.
SELECT endTimestamp(periodset '{[2012-01-01, 2012-01-03), (2012-01-03, 2012-01-05)}'); -- "2012-01-05"
Obtener la enésima marca de tiempo diferente
timestampN({timestampset,periodset},integer): timestamptz
La función no tiene en cuenta si los límites son inclusivos o no.
SELECT timestampN(periodset '{[2012-01-01, 2012-01-03), (2012-01-03, 2012-01-05)}', 3); -- "2012-01-04"
Obtener las marcas de tiempo diferentes
timestamps({timestampset,periodset}): timestampset
La función no tiene en cuenta si los límites son inclusivos o no.
SELECT timestamps(periodset '{[2012-01-01, 2012-01-03), (2012-01-03, 2012-01-05)}'); -- "{"2012-01-01", "2012-01-03", "2012-01-05"}"
Obtener el número de períodos
numPeriods(periodset): integer
SELECT numPeriods(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-04], [2012-01-05, 2012-01-06)}'); -- 3
Obtener el período inicial
startPeriod(periodset): period
SELECT startPeriod(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-04], [2012-01-05, 2012-01-06)}'); -- "[2012-01-01,2012-01-03)"
Obtener el período final
endPeriod(periodset): period
SELECT endPeriod(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-04], [2012-01-05, 2012-01-06)}'); -- "[2012-01-05,2012-01-06)"
Obtener el enésimo período
periodN(periodset,integer): period
SELECT periodN(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-04], [2012-01-05, 2012-01-06)}', 2); -- "[2012-01-04,2012-01-04]"
Obtener los períodos
periods(periodset): period[]
SELECT periods(periodset '{[2012-01-01, 2012-01-03), [2012-01-04, 2012-01-04], [2012-01-05, 2012-01-06)}'); -- "{"[2012-01-01,2012-01-03)", "[2012-01-04,2012-01-04]", "[2012-01-05,2012-01-06)"}"
Desplazar el valor de tiempo con un intervalo
shift({timestampset,period,periodset}): {timestampset,period,periodset}
SELECT shift(timestampset '{2001-01-01, 2001-01-03, 2001-01-05}', '1 day'::interval); -- "{2001-01-02, 2001-01-04, 2001-01-06}" SELECT shift(period '[2001-01-01, 2001-01-03]', '1 day'::interval); -- "[2001-01-02, 2001-01-04]" SELECT shift(periodset '{[2001-01-01, 2001-01-03], [2001-01-04, 2001-01-05]}', '1 day'::interval); -- "{[2001-01-02, 2001-01-04], [2001-01-05, 2001-01-06]}"
Redondear los límites de un rango flotante a un número de decimales
setPrecision(floatrange,integer): floatrange
SELECT setPrecision(floatrange '[1.123456789,2.123456789)', 3); -- "[1.123,2.123)" SELECT setPrecision(floatrange '(,2.123456789]', 3); -- "(,2.123]" SELECT setPrecision(floatrange '[1.123456789, inf)', 3); -- "[1.123,Infinity)"
Los operadores de comparación (=
, <
, etc.) requieren que los argumentos izquierdo y derecho sean del mismo tipo. Exceptuando la igualdad y la no igualdad, los otros operadores de comparación no son útiles en el mundo real, pero permiten construir índices de árbol B en tipos de tiempo. Para los valores de período, los operadores comparan primero el límite inferior y luego el límite superior. Para los valores de conjunto de marcas de tiempo y conjunto de períodos, los operadores comparan primero los períodos delimitadores y, si son iguales, comparan los primeros N instantes o períodos, donde N es el mínimo del número de instantes o períodos que componen ambos valores.
Los operadores de comparación disponibles para los tipos de tiempo se dan a continuación.
¿Son iguales los valores de tiempo?
time = time: boolean
SELECT period '[2012-01-01, 2012-01-04)' = period '[2012-01-01, 2012-01-04)'; -- true
¿Son diferentes los valores de tiempo?
time <> time: boolean
SELECT period '[2012-01-01, 2012-01-04)' <> period '[2012-01-03, 2012-01-05)'; -- true
¿Es el primer valor de tiempo menor que el segundo?
time < time: boolean
SELECT timestampset '{2012-01-01, 2012-01-04}' < timestampset '{2012-01-01, 2012-01-05}'; -- true
¿Es el primer valor de tiempo mayor que el segundo?
time > time: boolean
SELECT period '[2012-01-03, 2012-01-04)' > period '[2012-01-02, 2012-01-05)'; -- true
¿Es el primer valor de tiempo menor o igual que el segundo?
time <= time: boolean
SELECT periodset '{[2012-01-01, 2012-01-04)}' <= periodset '{[2012-01-01, 2012-01-05), [2012-01-06, 2012-01-07)}'; -- true
¿Es el primer valor de tiempo mayor o igual que el segundo?
time >= time: boolean
SELECT period '[2012-01-03, 2012-01-05)' >= period '[2012-01-03, 2012-01-04)'; -- true
Los operadores de conjuntos disponibles para los tipos de tiempo se dan a continuación.
Unión de valores de tiempo
time + time: time
SELECT timestampset '{2011-01-01, 2011-01-03, 2011-01-05}' + timestampset '{2011-01-03, 2011-01-06}'; -- "{2011-01-01, 2011-01-03, 2011-01-05, 2011-01-06}" SELECT period '[2011-01-01, 2011-01-05)' + period '[2011-01-03, 2011-01-07)'; -- "[2011-01-01, 2011-01-07)" SELECT periodset '{[2011-01-01, 2011-01-03), [2011-01-04, 2011-01-05)}' + period '[2011-01-03, 2011-01-04)'; -- "{[2011-01-01, 2011-01-05)}"
Intersección de valores de tiempo
time * time: time
SELECT timestampset '{2011-01-01, 2011-01-03}' * timestampset '{2011-01-03, 2011-01-05}'; -- "{2011-01-03}" SELECT period '[2011-01-01, 2011-01-05)' * period '[2011-01-03, 2011-01-07)'; -- "[2011-01-03, 2011-01-05)"
Diferencia de valores de tiempo
time - time: time
SELECT period '[2011-01-01, 2011-01-05)' - period '[2011-01-03, 2011-01-07)'; -- "[2011-01-01, 2011-01-03)" SELECT period '[2011-01-01, 2011-01-05]' - period '[2011-01-03, 2011-01-04]' -- "{[2011-01-01,2011-01-03), (2011-01-04,2011-01-05]}" SELECT periodset '{[2011-01-01, 2011-01-06], [2011-01-07, 2011-01-10]}' - periodset '{[2011-01-02, 2011-01-03], [2011-01-04, 2011-01-05], [2011-01-08, 2011-01-09]}'; -- "{[2011-01-01,2011-01-02), (2011-01-03,2011-01-04), (2011-01-05,2011-01-06], [2011-01-07,2011-01-08), (2011-01-09,2011-01-10]}"
A continuación se presentan los operadores topológicos disponibles para los tipos de tiempo.
¿Se superponen los valores de tiempo (tienen instantes en común)?
{timestampset,period,periodset} && {timestampset,period,periodset}: boolean
SELECT period '[2011-01-01, 2011-01-05)' && period '[2011-01-02, 2011-01-07)'; -- true
¿Contiene el primer valor de tiempo el segundo?
{timestampset,period,periodset} @> time: boolean
SELECT period '[2011-01-01, 2011-05-01)' @> period '[2011-02-01, 2011-03-01)'; -- true SELECT period '[2011-01-01, 2011-05-01)' @> timestamptz '2011-02-01'; -- true
¿Está el primer valor de tiempo contenido en el segundo?
time <@ {timestampset,period,periodset}: boolean
SELECT period '[2011-02-01, 2011-03-01)' <@ period '[2011-01-01, 2011-05-01)'; -- true SELECT timestamptz '2011-01-10' <@ period '[2011-01-01, 2011-05-01)'; -- true
¿Es el primer valor de tiempo adyacente al segundo?
time -|- time: boolean
SELECT period '[2011-01-01, 2011-01-05)' -|- timestampset '{2011-01-05, 2011-01-07}'; -- true SELECT periodset '{[2012-01-01, 2012-01-02]}' -|- period '[2012-01-02, 2012-01-03)'; -- false
En PostgreSQL, los operadores de rango <<
, &<
, >>
, &>
y -|-
solo aceptan rangos como argumento izquierdo o derecho. Extendimos estos operadores para rangos númericos de modo que un argumento puede ser un número entero o flotante.
Los operadores de posición relativa disponibles para los tipos de tiempo y tipos de rango se dan a continuación.
¿Está el primer número o valor de rango estrictamente a la izquierda del segundo?
{number,range} << {number,range}: boolean
SELECT intrange '[15, 20)' << 20; -- true
¿Está el primer número o valor de rango estrictamente a la derecha del segundo?
{number,range} >> {number,range}: boolean
SELECT intrange '[15, 20)' >> 10; -- true
¿No está el primer número o valor de rango a la derecha del segundo?
{number,range} &< {number,range}: boolean
SELECT intrange '[15, 20)' &< 18; -- false
¿No está el primer número o valor de rango a la izquierda del segundo?
{number,range} &> {number,range}: boolean
SELECT period '[2011-01-01, 2011-01-03)' &> period '[2011-01-01, 2011-01-05)'; -- true SELECT intrange '[15, 20)' &> 30; -- true
¿Es el primer número o valor de rango adyacente al segundo?
{number,range} -|- {number,range}: boolean
SELECT floatrange '[15, 20)' -|- 20; -- true
¿Es el primer valor de tiempo estrictamente anterior al segundo?
time <<# time: boolean
SELECT period '[2011-01-01, 2011-01-03)' <<# timestampset '{2011-01-03, 2011-01-05}'; -- true
¿Es el primer valor de tiempo estrictamente posterior al segundo?
time #>> time: boolean
SELECT period '[2011-01-04, 2011-01-05)' #>> periodset '{[2011-01-01, 2011-01-04), [2011-01-05, 2011-01-06)}'; -- true
¿No es el primer valor de tiempo posterior al segundo?
time &<# time: boolean
SELECT timestampset '{2011-01-02, 2011-01-05}' &<# period '[2011-01-01, 2011-01-05)'; -- false
¿No es el primer valor de tiempo anterior al segundo?
time #&> time: boolean
SELECT timestamp '2011-01-01' #&> period '[2011-01-01, 2011-01-05)'; -- true
Las funciones agregadas temporales generalizan las funciones agregadas tradicionales. Su semántica es que calculan el valor de la función en cada instante de la unión de las extensiones temporales de los valores a agregar. En contraste, recuerde que todas las otras funciones que manipulan tipos de tiempo calculan el valor de la función en cada instante de la intersección de las extensiones temporales de los argumentos.
Las funciones agregadas temporales son las siguientes:
La función tcount
generaliza la función tradicional count
. El conteo temporal se puede utilizar para calcular en cada momento el número de objetos disponibles (por ejemplo, el número of períodos). La función tcount
devuelve un entero temporal (ver el Capítulo 3).
La función extent
devuelve un período delimitador que engloba un conjunto de valores de tiempo.
Del mismo modo, hay una función agregada para los tipos de rango:
La función extent
devuelve un rango delimitador que engloba un conjunto de valores de rango.
La unión es una operación a muy útil para los tipos de tiempo. Como hemos visto en la Sección 2.1.6, podemos calcular la unión de dos valores de tiempo usando el operador +
. Sin embargo, también es muy útil tener una versión agregada del operador de unión para combinar un número arbitrario de valores. La función tunion
se puede utilizar para este propósito.
Conteo temporal
tcount({timestampset,period,periodset}): {tinti,tints}
WITH times(ts) AS ( SELECT timestampset '{2000-01-01, 2000-01-03, 2000-01-05}' UNION SELECT timestampset '{2000-01-02, 2000-01-04, 2000-01-06}' UNION SELECT timestampset '{2000-01-01, 2000-01-02}' ) SELECT tcount(ts) FROM times; -- "{2@2000-01-01, 2@2000-01-02, 1@2000-01-03, 1@2000-01-04, 1@2000-01-05, 1@2000-01-06}" WITH periods(ps) AS ( SELECT periodset '{[2000-01-01, 2000-01-02], [2000-01-03, 2000-01-04]}' UNION SELECT periodset '{[2000-01-01, 2000-01-04], [2000-01-05, 2000-01-06]}' UNION SELECT periodset '{[2000-01-02, 2000-01-06]}' ) SELECT tcount(ps) FROM periods; -- {[2@2000-01-01, 3@2000-01-02], (2@2000-01-02, 3@2000-01-03, 3@2000-01-04], (1@2000-01-04, 2@2000-01-05, 2@2000-01-06]}
Período delimitador
extent({timestampset,period,periodset}): period
WITH times(ts) AS ( SELECT timestampset '{2000-01-01, 2000-01-03, 2000-01-05}' UNION SELECT timestampset '{2000-01-02, 2000-01-04, 2000-01-06}' UNION SELECT timestampset '{2000-01-01, 2000-01-02}' ) SELECT extent(ts) FROM times; -- "[2000-01-01, 2000-01-06]" WITH periods(ps) AS ( SELECT periodset '{[2000-01-01, 2000-01-02], [2000-01-03, 2000-01-04]}' UNION SELECT periodset '{[2000-01-01, 2000-01-04], [2000-01-05, 2000-01-06]}' UNION SELECT periodset '{[2000-01-02, 2000-01-06]}' ) SELECT extent(ps) FROM periods; -- "[2000-01-01, 2000-01-06]"
Rango delimitador
extent(range): range
WITH ranges(r) AS ( SELECT floatrange '[1, 4)' UNION SELECT floatrange '(5, 8)' UNION SELECT floatrange '(7, 9)' ) SELECT extent(r) FROM ranges; -- "[1,9)"
Unión temporal
tunion({timestampset,period,periodset}): {timestampset,periodset}
WITH times(ts) AS ( SELECT timestampset '{2000-01-01, 2000-01-03, 2000-01-05}' UNION SELECT timestampset '{2000-01-02, 2000-01-04, 2000-01-06}' UNION SELECT timestampset '{2000-01-01, 2000-01-02}' ) SELECT tunion(ts) FROM times; -- "{2000-01-01, 2000-01-02, 2000-01-03, 2000-01-04, 2000-01-05, 2000-01-06}" WITH periods(ps) AS ( SELECT periodset '{[2000-01-01, 2000-01-02], [2000-01-03, 2000-01-04]}' UNION SELECT periodset '{[2000-01-02, 2000-01-03], [2000-01-05, 2000-01-06]}' UNION SELECT periodset '{[2000-01-07, 2000-01-08]}' ) SELECT tunion(ps) FROM periods; -- "{[2000-01-01, 2000-01-04], [2000-01-05, 2000-01-06], [2000-01-07, 2000-01-08]}"