Bounding Box Operations

Topological Operations

The topological operations available for the set and span types are given next.

  • Do the values overlap (have values in common)?

    {set,spans} && {set,spans} → boolean

    SELECT intset '{1, 3}' && intset '{2, 3, 4}';
    -- true
    SELECT floatspan '[1, 3)' && floatspan '[3, 4)';
    -- false
    SELECT tstzspan '[2001-01-01, 2001-01-05)' && tstzspan '[2001-01-02, 2001-01-07)';
    -- true
    SELECT floatspanset '{[1, 5),[6, 8)}' && floatspan '[1, 6)';
    -- true
    
  • Does the first value contain the second one?

    {set,spans} @> {base,set,spans} → 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
    
  • Is the first value contained by the second one?

    {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 tstzspan '[2001-02-01, 2001-03-01)' <@ tstzspan '[2001-01-01, 2001-05-01)';
    -- true
    SELECT floatspanset '{[1,2],[3,4]}' <@ floatspan '[1, 6]';
    -- true
    
  • Is the first value adjacent to the second one?

    spans -|- spans → boolean

    SELECT intspan '[2, 6)' -|- intspan '[6, 7)';
    -- true
    SELECT floatspan '[2, 5)' -|- floatspan '(5, 6)';
    -- false
    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)';
    -- false
    

Position Operations

The position operations available for set and span types are given next. Notice that the operators for time types have an additional # to distinguish them from the operators for number types.

  • Is the first value strictly left of the second one?

    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
    
  • Is the first value strictly to the right of the second one?

    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
    
  • Is the first value not to the right of the second one?

    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
    
  • Is the first value not to the left of the second one?

    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
    

Bounding Box Splitting

When creating indexes for set or span set types, what is stored in the index is not the actual value but instead, a bounding box that represents the value. In this case, the index will provide a list of candidate values that may satisfy the query predicate, and a second step is needed to filter out candidate values by computing the query predicate on the actual values.

However, when the bounding boxes have a large empty space not covered by the actual values, the index will generate many candidate values that do not satisfy the query predicate, which reduces the efficiency of the index. In these situations, it may be better to represent a value not with a single bounding box, but instead with multiple bounding boxes. This increases considerably the efficiency of the index, provided that the index is able to manage multiple bounding boxes per value. The following functions are used for generating multiple spans from a single set or span set value.

  • Return an array of N spans obtained by merging the elements of a set or the spans of a spanset

    splitNSpans(set, integer) → span[]

    splitNSpans(spanset, integer) → span[]

    The last argument specifies the number of output spans. If the number of input elements or spans is less than the given number, the resulting array will have one span per input element or span. Otherwise, the given number of output spans will be obtained by merging several consecutive input elements or spans.

    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)"}
    
  • Return an array of spans obtained by merging N consecutive elements of a set or N consecutive spans of a spanset

    splitEachNSpans(set, integer) → span[]

    splitEachNSpans(spanset, integer) → span[]

    The last argument specifies the number of input elements that are merged to produce an output span. If the number of input elements is less than the given number, the resulting array will have one output span per element. Otherwise, the given number of consecutive input elements will be merged into a single output span in the answer. Notice that, contrary to the splitNSpans function, the number of spans in the result depends on the number of input elements or spans.

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