A continuación se presentan los operadores topológicos disponibles para los tipos de conjunto y de rango.
Un valor, el rango que contiene únicamente ese valor y el conjunto de rangos que contiene únicamente ese rango denotan el mismo conjunto, al igual que un rango y el conjunto de rangos que contiene únicamente a él. Todas las operaciones dan la misma respuesta para todas estas escrituras.
Un conjunto de rangos es una unión de rangos disjuntos. Las operaciones &&, @>, <@ y ~= responden sobre el valor mismo, por lo que un valor que cae en un hueco de un conjunto de rangos no está contenido en él. La operación -|- y las operaciones de posición de la sección siguiente responden sobre la caja delimitadora del valor, el rango más pequeño que lo contiene: los huecos de un conjunto de rangos no son fronteras de él.
¿Se superponen los valores (tienen valores en común)?
{set,spans} && {set,spans} → boolean
SELECT intset '{1, 3}' && intset '{2, 3, 4}';
-- true
SELECT floatspan '[1, 3)' && floatspan '[3, 4)';
-- false
SELECT floatspanset '{[1, 5),[6, 8)}' && floatspan '[1, 6)';
-- true
SELECT tstzspan '[2001-01-01, 2001-01-05)' && tstzspan '[2001-01-02, 2001-01-07)';
-- true
¿Contiene el primer valor el segundo?
{set,spans} @> {base,set,span} → boolean
SELECT floatset '{1.5, 2.5}' @> 2.5;
-- true
SELECT tstzspan '[2001-01-01, 2001-05-01)' @> timestamptz '2001-02-01';
-- true
SELECT floatspanset '{[1, 2),(2, 3)}' @> 2.0;
-- false
¿Está el primer valor contenido en el segundo?
{base,set,spans} <@ {set,spans} → boolean
SELECT timestamptz '2001-01-10' <@ tstzspan '[2001-01-01, 2001-05-01)';
-- true
SELECT floatspan '[2, 5]' <@ floatspan '[1, 5)';
-- false
SELECT floatspanset '{[1,2],[3,4]}' <@ floatspan '[1, 6]';
-- true
SELECT tstzspan '[2001-02-01, 2001-03-01)' <@ tstzspan '[2001-01-01, 2001-05-01)';
-- true
¿Es el primer valor adyacente al segundo? Dos valores son adyacentes cuando se tocan sin solaparse, es decir, cuando comparten una frontera y no tienen ningún valor en común en ella. Para los tipos base continuos float y timestamptz, un límite compartido es ese contacto. Para los tipos base discretos int, bigint y date, cuyos rangos se almacenan en forma normal, significa valores consecutivos.
spans -|- spans → boolean
SELECT intspan '[2, 6)' -|- intspan '[6, 7)';
-- true
SELECT intspan '[1, 5]' -|- intspan '[6, 10]';
-- true
SELECT intspan '[1, 5]' -|- intspan '[5, 10]';
-- false
SELECT floatspan '[2, 5)' -|- floatspan '(5, 6)';
-- true
SELECT floatspan '[1, 5]' -|- floatspan '[5, 9]';
-- true
SELECT floatspanset '{[2, 3],[4, 5)}' -|- floatspan '(5, 6)';
-- true
SELECT tstzspanset '{[2001-01-01, 2001-01-02]}' -|- tstzspan '[2001-01-02, 2001-01-03)';
-- true
Un conjunto de rangos responde como su caja delimitadora, y las tres escrituras de un valor coinciden:
SELECT intspanset '{[1,3), [5,8), [10,12)}' -|- 3;
-- false
SELECT intspanset '{[1,3), [5,8), [10,12)}' -|- intspan '[3,3]';
-- false
SELECT intspanset '{[1,3), [5,8), [10,12)}' -|- intspanset '{[3,3]}';
-- false
SELECT intspanset '{[1,3), [5,8), [10,12)}' -|- 12;
-- true
Los operadores de posición disponibles para los tipos de conjunto y de rango se dan a continuación. Observe que los operadores para tipos de tiempo tienen un # adicional para distinguirlos de los operadores para tipos de números.
¿Está el primer valor estrictamente a la izquierda del segundo?
numbers << numbers → boolean times <<# times → boolean
SELECT intspan '[15, 20)' << 20;
-- true
SELECT intspanset '{[15, 17],[18, 20)}' << 20;
-- true
SELECT floatspan '[15, 20)' << floatspan '(15, 20)';
-- false
SELECT dateset '{2001-01-01, 2001-01-02}' <<# dateset '{2001-01-03, 2001-01-05}';
-- true
¿Está el primer valor estrictamente a la derecha del segundo?
numbers >> numbers → boolean times #>> times → boolean
SELECT intspan '[15, 20)' >> 10;
-- true
SELECT floatspan '[15, 20)' >> floatspan '[5, 10]';
-- true
SELECT floatspanset '{[15, 17], [18, 20)}' >> floatspan '[5, 10]';
-- true
SELECT tstzspan '[2001-01-04, 2001-01-05)' #>>
tstzspanset '{[2001-01-01, 2001-01-04), [2001-01-05, 2001-01-06)}';
-- true
¿No está el primer valor a la derecha del segundo?
numbers &< numbers → boolean times &<# times → boolean
SELECT intspan '[15, 20)' &< 18;
-- false
SELECT intspanset '{[15, 16],[17, 18)}' &< 18;
-- true
SELECT floatspan '[15, 20)' &< floatspan '[10, 20]';
-- true
SELECT dateset '{2001-01-02, 2001-01-05}' &<# dateset '{2001-01-01, 2001-01-04}';
-- false
¿No está el primer valor a la izquierda del segundo?
numbers &> numbers → boolean times #&> times → boolean
SELECT intspan '[15, 20)' &> 30;
-- true
SELECT floatspan '[1, 6]' &> floatspan '(1, 3)';
-- false
SELECT floatspanset '{[1, 2],[3, 4]}' &> floatspan '(1, 3)';
-- false
SELECT timestamp '2001-01-01' #&> tstzspan '[2001-01-01, 2001-01-05)';
-- true
Al crear índices para tipos de conjuntos o conjunto de rangos, lo que se almacena en el índice no es el valor real, sino un cuadro delimitador que representa el valor. En este caso, el índice proporcionará una lista de valores candidatos que pueden satisfacer el predicado de la consulta, y se necesita un segundo paso para filtrar los valores candidatos calculando el predicado de la consulta sobre los valores reales.
Sin embargo, cuando los cuadros delimitadores tienen un gran espacio vacío no cubierto por los valores reales, el índice generará muchos valores candidatos que no satisfacen el predicado de la consulta, lo que reduce la eficiencia del índice. En estas situaciones, puede ser mejor representar un valor no con un cuadro delimitador único, sino con múltiples cuadros delimitadores. Esto aumenta considerablemente la eficiencia del índice, siempre que el índice sea capaz de gestionar múltiples cuadros delimitadores por valor. Las siguientes funciones se utilizan para generar múltiples rangos a partir de un único valor de conjunto o conjunto de rangos.
Devuelve una matriz de N rangos obtenida fusionando los elementos de un conjunto o los rangos de un conjunto de rangos
splitNSpans(set, integer) → span[] splitNSpans(spanset, integer) → span[]
El último argumento especifica el número de rangos de salida. Si el número de elementos o rangos de entrada es menor que el número especificado, la matriz resultante tendrá un rango por elemento o rango de entrada. De lo contrario, el número especificado de rangos de salida se obtendrá fusionando elementos o rangos de entrada consecutivos.
SELECT splitNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 1);
/* {"[1, 11)"} */
SELECT splitNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 3);
-- {"[1, 5)","[5, 8)","[8, 11)"}
SELECT splitNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 6);
-- {"[1, 3)","[3, 5)","[5, 7)","[7, 9)","[9, 10)","[10, 11)"}
SELECT splitNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 12);
/* {"[1, 2)","[2, 3)","[3, 4)","[4, 5)","[5, 6)","[6, 7)","[7, 8)","[8, 9)",
"[9, 10)","[10, 11)"} */
SELECT splitNSpans(intspanset '{[1, 2), [3, 4), [5, 6), [7, 8), [9, 10)}');
-- {"[1, 2)","[3, 4)","[5, 6)","[7, 8)","[9, 10)"}
SELECT splitNSpans(floatspanset '{[1, 2), [3, 4), [5, 6), [7, 8), [9, 10)}', 3);
-- {"[1, 4)","[5, 8)","[9, 10)"}
SELECT splitNSpans(datespanset '{[2000-01-01, 2000-01-04), [2000-01-05, 2000-01-10)}', 3);
-- {"[2000-01-01, 2000-01-04)","[2000-01-05, 2000-01-10)"}
Devuelve una matriz de rangos obtenida fusionando N elementos consecutivos de un conjunto o N rangos consecutivos de un conjunto de rangos
splitEachNSpans(set, integer) → span[] splitEachNSpans(spanset, integer) → span[]
El último argumento especifica el número de elementos de entrada que se fusionan para producir un rango de salida. Si la cantidad de elementos de entrada es menor que el número especificado, la matriz resultante tendrá un rango de salida por elemento. De lo contrario, la cantidad especificada de elementos de entrada consecutivos se fusionará en un único rango de salida en la respuesta. Observe que, a diferencia de la función splitNSpans, el número de rangos en el resultado depende del número de elementos o de rangos de entrada.
SELECT splitEachNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 1);
/* {"[1, 2)","[2, 3)","[3, 4)","[4, 5)","[5, 6)","[6, 7)","[7, 8)","[8, 9)",
"[9, 10)","[10, 11)"} */
SELECT splitEachNSpans(intspanset '{[1, 2), [3, 4), [5, 6), [7, 8), [9, 10)}', 3);
-- {"[1, 6)","[7, 10)"}
SELECT splitEachNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 6);
-- {"[1, 7)","[7, 11)"}
SELECT splitEachNSpans(intset '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}', 12);
-- {"[1, 11)"}