Capítulo 2. Tipos de tiempo y tipos de rango

Tabla de contenidos

2.1. Funciones y operadores para tipos de tiempo y de rango
2.1.1. Funciones de constructor
2.1.2. Conversión de tipos
2.1.3. Funciones de accesor
2.1.4. Funciones de modificación
2.1.5. Operadores de comparación
2.1.6. Operadores de conjuntos
2.1.7. Operadores topológicos
2.1.8. Operadores de posición relativa
2.1.9. Funciones agregadas
2.2. Indexación de tipos de tiempo

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.

2.1. Funciones y operadores para tipos de tiempo y de rango

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.

2.1.1. Funciones de constructor

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.

  • Constructor para timestampset

    timestampset(timestamptz[]): timestampset

    SELECT timestampset(ARRAY[timestamptz '2012-01-01 08:00:00', '2012-01-03 09:30:00']);
    -- "{2012-01-01 08:00:00+00, 2012-01-03 09:30:00+00}"
    

El tipo periodset tiene una función constructora que acepta un solo argumento que es una matriz de valores de period.

  • Constructor para periodset

    periodset(period[]): periodset

    SELECT periodset(ARRAY[period '[2012-01-01 08:00:00, 2012-01-01 08:10:00]',
    -- '[2012-01-01 08:20:00, 2012-01-01 08:40:00]']);
    

2.1.2. Conversión de tipos

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 timestamptza 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)"
    

2.1.3. Funciones de accesor

  • 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)"}"
    

2.1.4. Funciones de modificación

  • 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)"
    

2.1.5. Operadores de comparación

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
    

2.1.6. Operadores de conjuntos

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]}"
    

2.1.7. Operadores topológicos

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
    

2.1.8. Operadores de posición relativa

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
    

2.1.9. Funciones agregadas

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]}"