# Temporal Types: Analytics Operations

## Simplification

- Return a temporal float or a temporal point simplified ensuring that consecutive values are at least a certain distance or time interval apart &Z_support; &geography_support;

  `minDistSimplify({tfloat,tpoint},mindist float) → {tfloat,tpoint}`

  `minTimeDeltaSimplify({tfloat,tpoint},mint interval) → {tfloat,tpoint}`

  In the case of temporal points, the distance is specified in the units of the coordinate system. Notice that simplification applies only to temporal sequences or sequence sets with linear interpolation. In all other cases, a copy of the given temporal value is returned.

      SELECT minDistSimplify(tfloat '[1@2001-01-01,2@2001-01-02,3@2001-01-04,4@2001-01-05]', 1);
      -- [1@2001-01-01, 3@2001-01-04, 4@2001-01-05]
      SELECT asText(minDistSimplify(tgeompoint '[Point(1 1 1)@2001-01-01,
        Point(2 2 2)@2001-01-02, Point(3 3 3)@2001-01-04, Point(5 5 5)@2001-01-05)', sqrt(3)));
      -- [POINT Z (1 1 1)@2001-01-01, POINT Z (3 3 3)@2001-01-04, POINT Z (5 5 5)@2001-01-05)
      SELECT asText(minDistSimplify(tgeompoint '[Point(1 1 1)@2001-01-01,
        Point(2 2 2)@2001-01-02, Point(3 3 3)@2001-01-04, Point(4 4 4)@2001-01-05)', sqrt(3)));
      -- [POINT Z (1 1 1)@2001-01-01, POINT Z (3 3 3)@2001-01-04, POINT Z (4 4 4)@2001-01-05]

      SELECT minTimeDeltaSimplify(tfloat '[1@2001-01-01, 2@2001-01-02, 3@2001-01-04,
        4@2001-01-05]', '1 day');
      -- [1@2001-01-01, 3@2001-01-04, 4@2001-01-05]
      SELECT asText(minTimeDeltaSimplify(tgeogpoint '[Point(1 1 1)@2001-01-01,
        Point(2 2 2)@2001-01-02, Point(3 3 3)@2001-01-04, Point(5 5 5)@2001-01-05)', '1 day'));
      -- [POINT Z (1 1 1)@2001-01-01, POINT Z (3 3 3)@2001-01-04, POINT Z (5 5 5)@2001-01-05]

- Return a temporal float or a temporal point simplified using the Douglas-Peucker algorithm &Z_support;

  `maxDistSimplify({tfloat,tgeompoint},maxdist float,syncdist=true) →`

  `{tfloat,tgeompoint}`

  `douglasPeuckerSimplify({tfloat,tgeompoint},maxdist float,syncdist=true) →`

  `{tfloat,tgeompoint}`

  The difference between the two functions is that `maxDistSimplify` uses a single-pass version of the algorithm whereas `douglasPeuckerSimplify` uses the standard recursive algorithm.

  The function removes values or points that are less than or equal to the distance passed as second argument. In the case of temporal points, the distance is specified in the units of the coordinate system. The third argument applies only for temporal points and specifies whether the spatial or the synchronized distance is used. Notice that simplification applies only to temporal sequences or sequence sets with linear interpolation. In all other cases, a copy of the given temporal value is returned.

      -- Only synchronous distance for temporal floats
      SELECT maxDistSimplify(tfloat '[1@2001-01-01, 2@2001-01-02, 1@2001-01-03, 3@2001-01-04,
        1@2001-01-05]', 1, false);
      -- [1@2001-01-01, 1@2001-01-03, 3@2001-01-04, 1@2001-01-05]
      -- Synchronous distance by default for temporal points
      SELECT asText(maxDistSimplify(tgeompoint '[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02,
        Point(3 1)@2001-01-03, Point(3 3)@2001-01-05, Point(5 1)@2001-01-06]', 2));
      -- [POINT(1 1)@2001-01-01, POINT(3 3)@2001-01-05, POINT(5 1)@2001-01-06]
      -- Spatial distance
      SELECT asText(maxDistSimplify(tgeompoint '[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02,
        Point(3 1)@2001-01-03, Point(3 3)@2001-01-05, Point(5 1)@2001-01-06]', 2, false));
      -- [POINT(1 1)@2001-01-01, POINT(5 1)@2001-01-06]

      -- Spatial vs synchronized Euclidean distance
      SELECT asText(douglasPeuckerSimplify(tgeompoint '[Point(1 1)@2001-01-01,
        Point(6 1)@2001-01-06, Point(7 4)@2001-01-07]', 2.3, false));
      -- [POINT(1 1)@2001-01-01, POINT(7 4)@2001-01-07]
      SELECT asText(douglasPeuckerSimplify(tgeompoint '[Point(1 1)@2001-01-01,
        Point(6 1)@2001-01-06, Point(7 4)@2001-01-07]', 2.3, true));
      -- [POINT(1 1)@2001-01-01, POINT(6 1)@2001-01-06, POINT(7 4)@2001-01-07]

  The difference between the spatial and the synchronized distance is illustrated in the last two examples above and in dist_vs_sed. In the first example, which uses the spatial distance, the second instant is removed since the perperdicular distance between `POINT(6 1)` and the line defined by `POINT(1 1)` and `POINT(7 4)` is equal to 2.23. On the contrary, in the second example the second instant is kept since the projection of `Point(6 2)` at timestamp `2001-01-06` over the temporal line segment results in `Point(6 3.5)` and the distance between the original point and its projection is 2.5.

  ### Difference between the spatial and the synchronous distance.

  A typical use for the `douglasPeuckerSimplify` function is to reduce the size of a dataset, in particular for visualization purposes. If the visualization is static, then the spatial distance should be preferred, if the visualization is dynamic or animated, the synchronized distance should be preferred.

## Reduction

- Sample a temporal value with respect to an interval

  `tsample(temporal,duration interval,torigin timestamptz='2000-01-03',`

  `interp='discrete') → temporal`

  If the origin is not specified, it is set by default to Monday, January 3, 2000. The given interval must be strictly greater than zero.

      SELECT tsample(tbool '[true@2001-01-01,false@2001-01-02]', '12 hours', '2001-01-01', 'step');
      -- [t@2001-01-01, f@2001-01-02]
      SELECT tsample(tint '{1@2001-01-01,5@2001-01-05}', '3 days', '2001-01-01');
      -- {1@2001-01-01}
      SELECT tsample(tfloat '[1@2001-01-01,5@2001-01-05]', '1 day', '2001-01-01');
      -- {1@2001-01-01, 2@2001-01-02, 3@2001-01-03, 4@2001-01-04, 5@2001-01-05}
      SELECT tsample(tfloat '[1@2001-01-01,5@2001-01-05]', '3 days', '2001-01-01');
      -- {1@2001-01-01, 4@2001-01-04}
      SELECT tsample(tfloat '[1@2001-01-01,5@2001-01-05]', '3 days', '2001-01-01', 'linear');
      -- [1@2001-01-01, 4@2001-01-04]

      SELECT asText(tsample(tgeompoint '[Point(1 1)@2001-01-01, Point(5 5)@2001-01-05]',
        '2 days', '2001-01-01'));
      -- {POINT(1 1)@2001-01-01, POINT(3 3)@2001-01-03, POINT(5 5)@2001-01-05}
      SELECT asText(tsample(tgeompoint '{[Point(1 1)@2001-01-01, Point(5 5)@2001-01-05],
        [Point(1 1)@2001-01-06, Point(5 5)@2001-01-08]}', '3 days', '2001-01-01'));
      -- {POINT(1 1)@2001-01-01, POINT(4 4)@2001-01-04, POINT(3 3)@2001-01-07}
      SELECT asText(tsample(tgeompoint '{[Point(1 1)@2001-01-01, Point(5 5)@2001-01-05],
        [Point(1 1)@2001-01-06, Point(5 5)@2001-01-08]}', '3 days', '2001-01-01', 'step'));
      -- Interp=Step;[POINT(1 1)@2001-01-01, POINT(4 4)@2001-01-04, POINT(3 3)@2001-01-07]

  fig_tsample illustrates the sampling of temporal floats with various interpolations. As shown in the figure, the sampling operation is best suited for temporal values with continuous interpolation.

  ### Sampling of temporal floats with discrete, step, and linear interpolation.

- Reduce the temporal precision of a temporal value with respect to an interval computing the time-weighted average/centroid in each time bin

  `tprecision({tnumber,tgeompoint},duration interval,torigin timestamptz='2000-01-03')`

  `→ {tnumber,tpoint}`

  If the origin is not specified, it is set by default to Monday, January 3, 2000. The given interval must be strictly greater than zero.

      SELECT tprecision(tint '[1@2001-01-01,5@2001-01-05,1@2001-01-09]','1 day',
        '2001-01-01');
      -- Interp=Step;[1@2001-01-01, 5@2001-01-05, 1@2001-01-09]
      SELECT tprecision(tfloat '[1@2001-01-01,5@2001-01-05,1@2001-01-09)','1 day',
        '2001-01-01');
      -- [1.5@2001-01-01, 4.5@2001-01-04, 4.5@2001-01-05, 1.5@2001-01-08]
      SELECT tprecision(tfloat '[1@2001-01-01,5@2001-01-05,1@2001-01-09]','1 day',
        '2001-01-01');
      -- [1.5@2001-01-01, 4.5@2001-01-04, 4.5@2001-01-05, 1.5@2001-01-08, 1@2001-01-09]
      SELECT tprecision(tfloat '[1@2001-01-01,5@2001-01-05,1@2001-01-09)','2 days',
        '2001-01-01');
      -- [2@2001-01-01, 4@2001-01-03, 4@2001-01-05, 2@2001-01-07]

      SELECT asText(tprecision(tgeompoint '[Point(1 1)@2001-01-01, Point(5 5)@2001-01-05,
        Point(1 1)@2001-01-09)', '1 day', '2001-01-01'));
      /* [POINT(1.5 1.5)@2001-01-01, POINT(4.5 4.5)@2001-01-04, POINT(4.5 4.5)@2001-01-05,
         POINT(1.5 1.5)@2001-01-08] */
      SELECT asText(tprecision(tgeompoint '[Point(1 1)@2001-01-01, Point(5 5)@2001-01-05,
        Point(1 1)@2001-01-09)', '2 days', '2001-01-01'));
      /* [POINT(2 2)@2001-01-01, POINT(4 4)@2001-01-03, POINT(4 4)@2001-01-05,
         POINT(2 2)@2001-01-07] */
      SELECT asText(tprecision(tgeompoint '[Point(1 1)@2001-01-01, Point(5 5)@2001-01-05,
        Point(1 1)@2001-01-09)', '4 days', '2001-01-01'));
      -- [POINT(3 3)@2001-01-01, POINT(3 3)@2001-01-05]

  Changing the precision of a temporal value is akin to changing its temporal granularity, for example, from timestamps to hours or days, although the precision can be set to an arbitrary interval, such as 2 hours and 15 minutes. fig_tprecision illustrates a change of temporal precision for temporal floats with various interpolations.

  ### Changing the precision of temporal floats with discrete, step, and linear interpolation.

## Similarity

- Return the discrete Hausdorff distance, the discrete Fréchet distance, or the Dynamic Time Warp (DTW) distance between two temporal values &Z_support; &geography_support;

  `hausdorffDistance({tnumber, tgeo}, {tnumber, tgeo}) → float`

  `frechetDistance({tnumber, tgeo}, {tnumber, tgeo}) → float`

  `dynTimeWarpDistance({tnumber, tgeo}, {tnumber, tgeo}) → float`

  These functions have a linear space complexity since only two rows of the distance matrix are allocated in memory. Nevertheless, their time complexity is quadratic in the number of instants of the temporal values. Therefore, the functions require considerable time for temporal values with large number of instants.

      SELECT hausdorffDistance(tfloat '[1@2001-01-01, 3@2001-01-03, 1@2001-01-06]',
       tfloat '[1@2001-01-01, 1.5@2001-01-02, 2.5@2001-01-03, 1.5@2001-01-04, 1.5@2001-01-05]');
      -- 0.5
      SELECT round(hausdorffDistance(tgeompoint '[Point(1 1)@2001-01-01, Point(3 3)@2001-01-03,
        Point(1 1)@2001-01-05]', tgeompoint '[Point(1.1 1.1)@2001-01-01,
        Point(2.5 2.5)@2001-01-02, Point(4 4)@2001-01-03, Point(3 3)@2001-01-04,
        Point(1.5 2)@2001-01-05]')::numeric, 6);
      -- 1.414214

      SELECT frechetDistance(tfloat '[1@2001-01-01, 3@2001-01-03, 1@2001-01-06]',
       tfloat '[1@2001-01-01, 1.5@2001-01-02, 2.5@2001-01-03, 1.5@2001-01-04, 1.5@2001-01-05]');
      -- 0.5
      SELECT round(frechetDistance(tgeompoint '[Point(1 1)@2001-01-01, Point(3 3)@2001-01-03,
        Point(1 1)@2001-01-05]', tgeompoint '[Point(1.1 1.1)@2001-01-01,
        Point(2.5 2.5)@2001-01-02, Point(4 4)@2001-01-03, Point(3 3)@2001-01-04,
        Point(1.5 2)@2001-01-05]')::numeric, 6);
      -- 1.414214

      SELECT dynTimeWarpDistance(tfloat '[1@2001-01-01, 3@2001-01-03, 1@2001-01-06]',
       tfloat '[1@2001-01-01, 1.5@2001-01-02, 2.5@2001-01-03, 1.5@2001-01-04, 1.5@2001-01-05]');
      -- 2
      SELECT round(dynTimeWarpDistance(tgeompoint '[Point(1 1)@2001-01-01,
        Point(3 3)@2001-01-03, Point(1 1)@2001-01-05]',
        tgeompoint '[Point(1.1 1.1)@2001-01-01, Point(2.5 2.5)@2001-01-02,
        Point(4 4)@2001-01-03, Point(3 3)@2001-01-04, Point(1.5 2)@2001-01-05]')::numeric, 6);
      -- 3.380776

- Return the correspondence pairs between two temporal values with respect to the discrete Fréchet distance or the Dynamic Time Warp Distance &Z_support; &geography_support; &SRF;

  `frechetDistancePath({tnumber, tgeo}, {tnumber, tgeo}) → {(i,j)}`

  `dynTimeWarpPath({tnumber, tgeo}, {tnumber, tgeo}) → {(i,j)}`

  The result is a set of pairs `(i,j)`. This function requires to allocate in memory a distance matrix whose size is quadratic in the number of instants of the temporal values. Therefore, the function will fail for temporal values with large number of instants depending on the available memory.

      SELECT frechetDistancePath(tfloat '[1@2001-01-01, 3@2001-01-03, 1@2001-01-06]',
       tfloat '[1@2001-01-01, 1.5@2001-01-02, 2.5@2001-01-03, 1.5@2001-01-04, 1.5@2001-01-05]');
      -- (0,0)
      -- (1,0)
      -- (2,1)
      -- (3,2)
      -- (4,2)
      SELECT frechetDistancePath(tgeompoint '[Point(1 1)@2001-01-01, Point(3 3)@2001-01-03,
        Point(1 1)@2001-01-05]', tgeompoint '[Point(1.1 1.1)@2001-01-01,
        Point(2.5 2.5)@2001-01-02, Point(4 4)@2001-01-03, Point(3 3)@2001-01-04,
        Point(1.5 2)@2001-01-05]');
      -- (0,0)
      -- (1,1)
      -- (2,1)
      -- (3,1)
      -- (4,2)

      SELECT dynTimeWarpPath(tfloat '[1@2001-01-01, 3@2001-01-03, 1@2001-01-06]',
       tfloat '[1@2001-01-01, 1.5@2001-01-02, 2.5@2001-01-03, 1.5@2001-01-04, 1.5@2001-01-05]');
      -- (0,0)
      -- (1,0)
      -- (2,1)
      -- (3,2)
      -- (4,2)
      SELECT dynTimeWarpPath(tgeompoint '[Point(1 1)@2001-01-01, Point(3 3)@2001-01-03,
        Point(1 1)@2001-01-05]', tgeompoint '[Point(1.1 1.1)@2001-01-01,
        Point(2.5 2.5)@2001-01-02, Point(4 4)@2001-01-03, Point(3 3)@2001-01-04,
        Point(1.5 2)@2001-01-05]');
      -- (0,0)
      -- (1,1)
      -- (2,1)
      -- (3,1)
      -- (4,2)

## Splitting Operations

When creating indexes for temporal 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 bounding boxes for a single temporal value.

- Return an array of N time spans obtained by merging the instants or segments of a temporal value &Z_support; &geography_support;

  `splitNSpans(temp, integer) → tstzspan[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. The last argument specifies the number of output spans. If the number of instants or segments is less than or equal to the given number, the resulting array will have one span per instant or segment of the temporal value. Otherwise, the given number of spans will be obtained by merging consecutive instants or segments.

      SELECT splitNSpans(ttext '{A@2000-01-01, B@2000-01-02, A@2000-01-03, B@2000-01-04,
        A@2000-01-05}', 1);
      -- {"[2000-01-01, 2000-01-05]"}
      SELECT splitNSpans(tfloat '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 2@2000-01-04,
        1@2000-01-05}', 2);
      -- {"[2000-01-01, 2000-01-03]","[2000-01-04, 2000-01-05]"}
      SELECT splitNSpans(tgeompoint '[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(1 1)@2000-01-03, Point(2 2)@2000-01-04, Point(1 1)@2000-01-05]', 2);
      -- {"[2000-01-01, 2000-01-03]","[2000-01-03, 2000-01-05]"}
      SELECT splitNSpans(tgeogpoint '{[Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02],
        [Point(1 1 1)@2000-01-03, Point(2 2 2)@2000-01-04], [Point(1 1 1)@2000-01-05]}', 2);
      -- {"[2000-01-01, 2000-01-04])","[2000-01-05, 2000-01-05])"}
      SELECT splitNSpans(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 2@2000-01-04,
        2@2000-01-05}', 6);
      /* {"[2000-01-01, 2000-01-01]","[2000-01-02, 2000-01-02]","[2000-01-03, 2000-01-03]",
          "[2000-01-04, 2000-01-04]","[2000-01-05, 2000-01-05]"} */
      SELECT splitNSpans(ttext '[A@2000-01-01, B@2000-01-02, A@2000-01-03, B@2000-01-04,
        A@2000-01-05]', 6);
      /* {"[2000-01-01, 2000-01-02]","[2000-01-02, 2000-01-03]",
          "[2000-01-03, 2000-01-04]","[2000-01-04, 2000-01-05]"} */

- Return an array of time spans obtained by merging N consecutive instants or segments of a temporal value &Z_support; &geography_support;

  `splitEachNSpans(temp, integer) → tstzspan[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. The last argument specifies the number of input instants or segments that are merged to produce an output span. If the number of input elements is less than or equal to the given number, the resulting array will have a single span per sequence. Otherwise, the given number of consecutive instants or segments will be merged into each output span. Notice that, contrary to the `splitNSpans` function, the number of spans in the result depends on the number of input instants or segments.

      SELECT splitEachNSpans(ttext '{A@2000-01-01, B@2000-01-02, A@2000-01-03, B@2000-01-04,
        A@2000-01-05}', 1);
      /* {"[2000-01-01, 2000-01-01]","[2000-01-02, 2000-01-02]","[2000-01-03, 2000-01-03]",
           "[2000-01-04, 2000-01-04]","[2000-01-05, 2000-01-05]} */
      SELECT splitEachNSpans(tfloat '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 2@2000-01-04,
        1@2000-01-05]', 2);
      --  {"[2000-01-01, 2000-01-03]","[2000-01-03, 2000-01-05]"}
      SELECT splitEachNSpans(tgeompoint '{[Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02],
        [Point(1 1 1)@2000-01-03, Point(2 2 2)@2000-01-04], [Point(1 1 1)@2000-01-05]}', 2);
      --  {"[2000-01-01, 2000-01-02]","[2000-01-03, 2000-01-04]","[2000-01-05, 2000-01-05]"}
      SELECT splitEachNSpans(tgeogpoint '[Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02,
        Point(1 1 1)@2000-01-03, Point(2 2 2)@2000-01-04, Point(1 1 1)@2000-01-05]', 6);
      -- {"[2000-01-01, 2000-01-05])"}
      SELECT splitEachNSpans(tgeogpoint '{[Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02],
        [Point(1 1 1)@2000-01-03, Point(2 2 2)@2000-01-04], [Point(1 1 1)@2000-01-05]}', 6);
      -- {"[2000-01-01, 2000-01-02]","[2000-01-03, 2000-01-04]","[2000-01-05, 2000-01-05]"}

- Return an array of N temporal boxes obtained by merging the instants or segments of a temporal number

  `splitNTboxes(tnumber, integer) → tbox[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. The last argument specifies the number of output boxes. If the number of input instants or segments is less than or equal to the given number, the resulting array will have one box per instant or segment of the temporal number. Otherwise, the specified number of boxes will be obtained by merging consecutive instants or segments.

      SELECT splitNTboxes(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05}', 1);
      -- {"TBOXINT XT([1, 5),[2000-01-01, 2000-01-05])"}
      SELECT splitNTboxes(tfloat '{[1@2000-01-01, 2@2000-01-02], [1@2000-01-03, 4@2000-01-04],
        [1@2000-01-05]}', 2);
      /* {"TBOXFLOAT XT([1, 4],[2000-01-01, 2000-01-04])",
          "TBOXFLOAT XT([1, 1],[2000-01-05, 2000-01-05])"} */
      SELECT splitNTboxes(tfloat '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', 3);
      /* {"TBOXFLOAT XT([1, 2],[2000-01-01, 2000-01-03])",
          "TBOXFLOAT XT([1, 4],[2000-01-03, 2000-01-04])",
          "TBOXFLOAT XT([1, 4],[2000-01-04, 2000-01-05])"} */
      SELECT splitNTboxes(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05}', 6);
      /* {"TBOXINT XT([1, 2),[2000-01-01, 2000-01-01])",
          "TBOXINT XT([2, 3),[2000-01-02, 2000-01-02])",
          "TBOXINT XT([1, 2),[2000-01-03, 2000-01-03])",
          "TBOXINT XT([4, 5),[2000-01-04, 2000-01-04])",
          "TBOXINT XT([1, 2),[2000-01-05, 2000-01-05])"} */
      SELECT splitNTboxes(tint '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', 6);
      /* {"TBOXINT XT([1, 3),[2000-01-01, 2000-01-02])",
          "TBOXINT XT([1, 3),[2000-01-02, 2000-01-03])",
          "TBOXINT XT([1, 5),[2000-01-03, 2000-01-04])",
          "TBOXINT XT([1, 5),[2000-01-04, 2000-01-05])"} */

- Return an array of temporal boxes obtained by merging N consecutive instants or segments of a temporal number

  `splitEachNTboxes(tnumber, integer) → tbox[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. The last argument specifies the number of input instants or segments that are merged to produce an output box. If the number of input instants or segments is less than or equal to the given number, the resulting array will have a single box per sequence. Otherwise, the specified number of consecutive instants or segments will be merged into each output box. Notice that, contrary to the `splitNTboxes` function, the number of boxes in the result depends on the number of input instants or segments.

      SELECT splitEachNTboxes(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05}', 1);
      /* {"TBOXINT XT([1, 2),[2000-01-01, 2000-01-01])",
          "TBOXINT XT([2, 3),[2000-01-02, 2000-01-02])",
          "TBOXINT XT([1, 2),[2000-01-03, 2000-01-03])",
          "TBOXINT XT([4, 5),[2000-01-04, 2000-01-04])"} */
      SELECT splitEachNTboxes(tint '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', 1);
      /* {"TBOXINT XT([1, 3),[2000-01-01, 2000-01-02])",
          "TBOXINT XT([1, 3),[2000-01-02, 2000-01-03])",
          "TBOXINT XT([1, 5),[2000-01-03, 2000-01-04])",
          "TBOXINT XT([1, 5),[2000-01-04, 2000-01-05])"} */
      SELECT splitEachNTboxes(tfloat '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', 3);
      /* {"TBOXFLOAT XT([1, 4],[2000-01-01, 2000-01-04])",
          "TBOXFLOAT XT([1, 4],[2000-01-04, 2000-01-05])"} */
      SELECT splitEachNTboxes(tfloat '{[1@2000-01-01, 2@2000-01-02], [1@2000-01-03, 4@2000-01-04],
        [1@2000-01-05]}', 6);
      /* {"TBOXFLOAT XT([1, 2],[2000-01-01, 2000-01-02])",
          "TBOXFLOAT XT([1, 4],[2000-01-03, 2000-01-04])",
          "TBOXFLOAT XT([1, 1],[2000-01-05, 2000-01-05])"} */

- Return either an array of N spatial boxes obtained by merging the segments of a (multi)line or an array of N spatiotemporal boxes obtained by merging the instants or segments of a temporal point &Z_support; &geography_support;

  `splitNStboxes(lines, integer) → stbox[]`

  `splitNStboxes(tpoint, integer) → stbox[]`

  For temporal points, the choice between instants or segments depends on whether the interpolation is discrete or continuous. The last argument specifies the number of output boxes. If the number of instants or segments is less than or equal to the given number, the resulting array will have either one box per segment of the (multi)line or one box per instant or segment of the temporal point. Otherwise, the specified number of boxes will be obtained by merging consecutive instants or segments.

      SELECT splitNStboxes(geometry 'Linestring(1 1,2 2,3 1,4 2,5 1)', 1);
      -- {"STBOX X((1,1),(5,2))"}
      SELECT splitNStboxes(geometry 'Linestring(1 1,2 2,3 1,4 2,5 1)', 2);
      -- {"STBOX X((1,1),(3,2))","STBOX X((3,1),(5,2))"}
      SELECT splitNStboxes(geography 'Linestring(1 1 1,2 2 1,3 1 1,4 2 1,5 1 1)', 6);
      /* {"SRID=4326;GEODSTBOX Z((1,1,1),(2,2,1))",
          "SRID=4326;GEODSTBOX Z((2,1,1),(3,2,1))",
          "SRID=4326;GEODSTBOX Z((3,1,1),(4,2,1))",
          "SRID=4326;GEODSTBOX Z((4,1,1),(5,2,1))"} */
      SELECT splitNStboxes(geometry 'MultiLinestring((1 1,2 2),(3 1,4 2),(5 1,6 2))', 2);
      -- {"STBOX X((1,1),(4,2))","STBOX X((5,1),(6,2))"}

      SELECT splitNStboxes(tgeompoint '{Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(3 1)@2000-01-03, Point(4 2)@2000-01-04, Point(5 1)@2000-01-05}', 1);
      -- {"STBOX XT(((1,1),(5,2)),[2000-01-01, 2000-01-05])"}
      SELECT splitNStboxes(tgeompoint '[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(3 1)@2000-01-03, Point(4 2)@2000-01-04, Point(5 1)@2000-01-05]');
      /* {"STBOX XT(((1,1),(2,2)),[2000-01-01, 2000-01-02])",
          "STBOX XT(((2,1),(3,2)),[2000-01-02, 2000-01-03])",
          "STBOX XT(((3,1),(4,2)),[2000-01-03, 2000-01-04])",
          "STBOX XT(((4,1),(5,2)),[2000-01-04, 2000-01-05])"} */
      SELECT splitNStboxes(tgeompoint '{[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02],
        [Point(3 1)@2000-01-03, Point(4 2)@2000-01-04], [Point(5 1)@2000-01-05]}', 2);
      /* {"STBOX XT(((1,1),(4,2)),[2000-01-01, 2000-01-04])",
          "STBOX XT(((5,1),(5,1)),[2000-01-05, 2000-01-05])"} */
      SELECT splitNStboxes(tgeogpoint '{Point(1 1 1)@2000-01-01, Point(2 2 1)@2000-01-02,
        Point(3 1 1)@2000-01-03, Point(4 2 1)@2000-01-04, Point(5 1 1)@2000-01-05}', 6);
      /* {"SRID=4326;GEODSTBOX ZT(((1,1,1),(1,1,1)),[2000-01-01, 2000-01-01])",
          "SRID=4326;GEODSTBOX ZT(((2,2,1),(2,2,1)),[2000-01-02, 2000-01-02])",
          "SRID=4326;GEODSTBOX ZT(((3,1,1),(3,1,1)),[2000-01-03, 2000-01-03])",
          "SRID=4326;GEODSTBOX ZT(((4,2,1),(4,2,1)),[2000-01-04, 2000-01-04])",
          "SRID=4326;GEODSTBOX ZT(((5,1,1),(5,1,1)),[2000-01-05, 2000-01-05])"} */
      SELECT splitNStboxes(tgeompoint '[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(3 1)@2000-01-03, Point(4 2)@2000-01-04, Point(5 1)@2000-01-05]', 6);
      /* {"STBOX XT(((1,1),(2,2)),[2000-01-01, 2000-01-02])",
          "STBOX XT(((2,1),(3,2)),[2000-01-02, 2000-01-03])",
          "STBOX XT(((3,1),(4,2)),[2000-01-03, 2000-01-04])",
          "STBOX XT(((4,1),(5,2)),[2000-01-04, 2000-01-05])"} */

- Return either an array of spatial boxes obtained by merging N consecutive segments of a (multi)line or an array of spatiotemporal boxes obtained by merging N consecutive instants or segments of a temporal point &Z_support; &geography_support;

  `splitEachNStboxes(lines, integer) → stbox[]`

  `splitEachNStboxes(tpoint, integer) → stbox[]`

  For temporal points, the choice between instants or segments depends on whether the interpolation is discrete or continuous. The last argument specifies the number of input instants or segments that are merged to produce an output box. If the number of instants or segments is less than or equal to the given number, the resulting array will have a single box per sequence. Otherwise, the specified number of consecutive instants or segments will be merged into each output box. Notice that, contrary to the `splitNStboxes` function, the number of boxes in the result depends on the number of input instants or segments.

      SELECT splitEachNStboxes(geometry 'Linestring(1 1,2 2,3 1,4 2,5 1)', 1);
      -- {"STBOX X((1,1),(5,2))"}
      SELECT splitEachNStboxes(geometry 'Linestring(1 1,2 2,3 1,4 2,5 1)', 2);
      -- {"STBOX X((1,1),(3,2))","STBOX X((3,1),(5,2))"}
      SELECT splitEachNStboxes(geography 'Linestring(1 1 1,2 2 1,3 1 1,4 2 1,5 1 1)', 6);
      /* {"SRID=4326;GEODSTBOX Z((1,1,1),(2,2,1))",
          "SRID=4326;GEODSTBOX Z((2,1,1),(3,2,1))",
          "SRID=4326;GEODSTBOX Z((3,1,1),(4,2,1))",
          "SRID=4326;GEODSTBOX Z((4,1,1),(5,2,1))"} */
      SELECT splitEachNStboxes(geometry 'MultiLinestring((1 1,2 2),(3 1,4 2),(5 1,6 2))', 2);
      -- {"STBOX X((1,1),(4,2))","STBOX X((5,1),(6,2))"}

      SELECT splitEachNStboxes(tgeompoint '{Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(3 1)@2000-01-03, Point(4 2)@2000-01-04, Point(5 1)@2000-01-05}', 1);
      /* {"STBOX XT(((1,1),(1,1)),[2000-01-01, 2000-01-01])",
          "STBOX XT(((2,2),(2,2)),[2000-01-02, 2000-01-02])",
          "STBOX XT(((3,1),(3,1)),[2000-01-03, 2000-01-03])",
          "STBOX XT(((4,2),(4,2)),[2000-01-04, 2000-01-04])",
          "STBOX XT(((5,1),(5,1)),[2000-01-05, 2000-01-05])"} */
      SELECT splitEachNStboxes(tgeompoint '[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(3 1)@2000-01-03, Point(4 2)@2000-01-04, Point(5 1)@2000-01-05]', 1);
      /* {"STBOX XT(((1,1),(2,2)),[2000-01-01, 2000-01-02])",
          "STBOX XT(((2,1),(3,2)),[2000-01-02, 2000-01-03])",
          "STBOX XT(((3,1),(4,2)),[2000-01-03, 2000-01-04])",
          "STBOX XT(((4,1),(5,2)),[2000-01-04, 2000-01-05])"} */
      SELECT splitEachNStboxes(tgeogpoint '{[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02],
        [Point(3 1)@2000-01-03, Point(4 2)@2000-01-04], [Point(5 1)@2000-01-05]}', 2);
      /* {"SRID=4326;GEODSTBOX XT(((1,1),(2,2)),[2000-01-01, 2000-01-02])",
          "SRID=4326;GEODSTBOX XT(((3,1),(4,2)),[2000-01-03, 2000-01-04])",
          "SRID=4326;GEODSTBOX XT(((5,1),(5,1)),[2000-01-05, 2000-01-05])"} */

## Multidimensional Tiling

Multidimensional tiling is the mechanism used to partition the domain of temporal values in bins or tiles of varying number of dimensions. In the case of a single dimension, the domain can be partitioned by value or by time using bins of the same size or duration, respectively. For temporal numbers, the domain can be partitioned in two-dimensional tiles of the same size for the value dimension and the same duration for the time dimension. For temporal points, the domain can be partitioned in space in two- or three-dimensional tiles, depending on the number of dimensions of the spatial coordinates. Finally, for temporal points, the domain can be partitioned in space and time using three- or four-dimensional tiles.

Multidimensional tiling can be used for various purposes. It can be used for computing multidimensional histograms, where the temporal values are aggregated according to the underlying partition of the domain. On the other hand, multidimensional tiling can also be used for indexing purposes, where the bounding box of a temporal value can be fragmented into multiple boxes in order to improve the efficiency of the index. Finally, multidimensional tiling can be used for fragmenting temporal values according to a multidimensional grid defined over the underlying domain. This enables the distribution of a dataset across a cluster of servers, where each server contains a partition of the dataset. The advantage of this partition mechanism is that it preserves proximitity in value/space and time, unlike the traditional hash-based partition mechanisms.

### Multidimensional tiling for temporal floats.

tiling illustrates multidimensional tiling for temporal floats. The two-dimensional domain is split into tiles having the same size for the value dimension and the same duration for the time dimension. Suppose that this tiling scheme is used for distribute a dataset across a cluster of six servers, as suggested by the gray pattern in the figure. In this case, the values are fragmented so each server will receive the data of contiguous tiles. This implies in particular that four nodes will receive one fragment of the temporal float depicted in the figure. One advantage of this distribution of data based on multidimensional tiling is that it reduces the data that needs to be exchanged between nodes when processing queries, a process typically referred to as reshuffling.

Many of the functions in this section are set-returning functions (also known as a table functions) since they typically return more than one value. In this case, the functions are marked with the &SRF; symbol.

### Bin Operations

- Return an array of bins that cover a value or time span with bins of the same size or duration

  `bins(numspans,size number,origin number=0) → span[]`

  `bins(datespans,duration interval,origin date='2000-01-03') → span[]`

  `bins(tstzspans,duration interval,origin timestamptz='2000-01-03') → span[]`

  If the origin is not specified, it is set by default to 0 for value spans and Monday, January 3, 2000 for time spans.

      SELECT bins(floatspan '[-10, -1]', 2.5, -7);
      -- {"[-12, -9.5)","[-9.5, -7)","[-7, -4.5)","[-4.5, -2)","[-2, 0.5)"}
      SELECT bins(intspan '[15, 25]', 2);
      -- {"[14, 16)","[16, 18)","[18, 20)","[20, 22)","[22, 24)","[24, 26)","[26, 28)"}
      SELECT index, span
      FROM unnest(bins(datespan '[2001-01-15, 2001-01-25]', '2 days'))
        WITH ORDINALITY t(span, index);
      -- 1 | [2001-01-15, 2001-01-17)
      -- 2 | [2001-01-17, 2001-01-19)
      -- 3 | [2001-01-19, 2001-01-21)
      -- ...
      SELECT index, span
      FROM unnest(bins(tstzspanset '{[2001-01-15, 2001-01-17],[2001-01-22, 2001-01-25]}',
        '2 days', '2001-01-02')) WITH ORDINALITY t(span, index);
      -- 1 | [2001-01-15, 2001-01-16)
      -- 2 | [2001-01-16, 2001-01-17]
      -- 3 | [2001-01-22, 2001-01-24)
      -- 4 | [2001-01-24, 2001-01-25]

- Return the bin that contains a number or a timestamp

  `getBin(number,size number,origin number=0) → span`

  `getBin(date,duration interval,origin date='2000-01-03') →`

  `getBin(timestamptz,duration interval,origin timestamptz='2000-01-03') →`

  `timestamptz`

  If the origin is not specified, it is set by default to 0 for value bins and to Monday, January 3, 2000 for time bins.

      SELECT getBin(2, 2);
      -- [2, 4)
      SELECT getBin(2, 2.5, 1.5);
      -- [1.5, 4)
      SELECT getBin('2001-01-04', interval '1 week');
      -- [2001-01-03, 2001-01-10)
      SELECT getBin('2001-01-04', interval '1 week', '2001-01-07');
      -- [2000-12-31, 2001-01-07)

### Tile Operations

- Return the set of tiles that covers a temporal box with tiles of the same size and/or duration &SRF;

  `valueTiles(tbox,vsize float,vorigin float=0) → {(index,tile)}`

  `timeTiles(tbox,duration interval,torigin timestamptz='2000-01-03') →`

  `{(index,tile)}`

  `valueTimeTiles(tbox,vsize float,duration interval,vorigin float=0,`

  `torigin timestamptz='2000-01-03') → {(index,tile)}`

  The result is a set of pairs `(index,tile)`. If the origin of the value and/or time dimension is not specified, it is set by default to 0 and to Monday, January 3, 2000, respectively.

      SELECT (gr).index, (gr).tile
      FROM (SELECT valueTiles(tfloat '[15@2001-01-15, 25@2001-01-25]'::tbox, 2.0) AS gr) t;
      -- 1 | TBOXFLOAT X([14, 16))
      -- 2 | TBOXFLOAT X([16, 18))
      -- 3 | TBOXFLOAT X([18, 20))
      -- ...
      SELECT (gr).index, (gr).tile
      FROM (SELECT timeTiles(tfloat '[15@2001-01-15, 25@2001-01-25]'::tbox, '2 days') AS gr) t;
      -- 1 | TBOX T([2001-01-15, 2001-01-17))
      -- 2 | TBOX T([2001-01-17, 2001-01-19))
      -- 3 | TBOX T([2001-01-19, 2001-01-21))
      -- ...
      SELECT (gr).index, (gr).tile
      FROM (SELECT valueTimeTiles(tfloat '[15@2001-01-15, 25@2001-01-25]'::tbox, 2.0, '2 days')
        AS gr) t;
      -- 1 | TBOX XT([14,16),[2001-01-15,2001-01-17))
      -- 2 | TBOX XT([16,18),[2001-01-15,2001-01-17))
      -- 3 | TBOX XT([18,20),[2001-01-15,2001-01-17))
      -- ...
      SELECT valueTimeTiles(tfloat '[15@2001-01-15,25@2001-01-25]'::tbox, 2.0, '2 days', 11.5);
      -- (1,"TBOX XT([13.5,15.5),[2001-01-15,2001-01-17))")
      -- (2,"TBOX XT([15.5,17.5),[2001-01-15,2001-01-17))")
      -- (3,"TBOX XT([17.5,19.5),[2001-01-15,2001-01-17))")
      -- ...

- Return the set of tiles that covers a spatiotemporal box with tiles of the same size and/or duration &Z_support; &SRF;

  `spaceTiles(stbox,xsize float,[ysize float,zsize float,]`

  `sorigin geompoint='Point(0 0 0)',borderInc bool=true) → {(index,tile)}`

  `timeTiles(stbox,duration interval,torigin timestamptz='2000-01-03',`

  `borderInc bool=true) → {(index,tile)}`

  `spaceTimeTiles(stbox,xsize float,[ysize float,zsize float,]duration interval,`

  `sorigin geompoint='Point(0 0 0)',torigin timestamptz='2000-01-03',`

  `borderInc bool=true) → {(index,tile)}`

  The result is a set of pairs `(index,tile)`. If the origin of the space and/or time dimension is not specified, it is set by default to `'Point(0 0 0)'` and to Monday, January 3, 2000, respectively. The optional argument `borderInc` states whether the upper border of the extent is included and thus, extra tiles containing the border are generated.

  In the case of a spatiotemporal grid, `ysize` and `zsize` are optional, the size for the missing dimensions is assumed to be equal to `xsize`. The SRID of the tile coordinates is determined by the input box and the sizes are given in the units of the SRID. If the origin for the spatial coordinates is given, which must be a point, its dimensionality and SRID should be equal to the one of box, otherwise an error is raised.

      SELECT spaceTiles(tgeompoint '[Point(3 3)@2001-01-15,
        Point(15 15)@2001-01-25]'::stbox, 2.0);
      -- (1,"STBOX X((2,2),(4,4))")
      -- (2,"STBOX X((4,2),(6,4))")
      -- (3,"STBOX X((6,2),(8,4))")
      -- ...
      SELECT timeTiles(tgeompoint '[Point(3 3)@2001-01-15,
        Point(15 15)@2001-01-25]'::stbox, '2 days');
      -- (1,"STBOX T([2001-01-15, 2001-01-17))")
      -- (2,"STBOX T([2001-01-17, 2001-01-19))")
      -- (3,"STBOX T([2001-01-19, 2001-01-21))")
      -- ...
      SELECT spaceTiles(tgeompoint 'SRID=3812;[Point(3 3)@2001-01-15,
        Point(15 15)@2001-01-25]'::stbox, 2.0, geometry 'Point(3 3)');
      -- (1,"SRID=3812;STBOX X((3,3),(5,5))")
      -- (2,"SRID=3812;STBOX X((5,3),(7,5))")
      -- (3,"SRID=3812;STBOX X((7,3),(9,5))")
      -- ...
      SELECT spaceTiles(tgeompoint '[Point(3 3 3)@2001-01-15,
        Point(15 15 15)@2001-01-25]'::stbox, 2.0, geometry 'Point(3 3 3)');
      -- (1,"STBOX Z((3,3,3),(5,5,5))")
      -- (2,"STBOX Z((5,3,3),(7,5,5))")
      -- (3,"STBOX Z((7,3,3),(9,5,5))")
      -- ...
      SELECT spaceTimeTiles(tgeompoint '[Point(3 3)@2001-01-15,
        Point(15 15)@2001-01-25]'::stbox, 2.0, interval '2 days');
      -- (1,"STBOX XT(((2,2),(4,4)),[2001-01-15,2001-01-17))")
      -- (2,"STBOX XT(((4,2),(6,4)),[2001-01-15,2001-01-17))")
      -- (3,"STBOX XT(((6,2),(8,4)),[2001-01-15,2001-01-17))")
      -- ...
      SELECT spaceTimeTiles(tgeompoint '[Point(3 3 3)@2001-01-15,
        Point(15 15 15)@2001-01-25]'::stbox, 2.0, interval '2 days',
        'Point(3 3 3)', '2001-01-15');
      -- (1,"STBOX ZT(((3,3,3),(5,5,5)),[2001-01-15,2001-01-17))")
      -- (2,"STBOX ZT(((5,3,3),(7,5,5))),[2001-01-15,2001-01-17)")
      -- (3,"STBOX ZT(((7,3,3),(9,5,5))),[2001-01-15,2001-01-17)")
      -- ...

- Return the temporal tile that covers a value and/or a timestamp &Z_support;

  `getValueTile(value float,vsize float,vorigin float=0.0,) → tbox`

  `getTboxTimeTile(time timestamptz,duration interval,`

  `torigin timestamptz='2000-01-03') → tbox`

  `getValueTimeTile(value float,time timestamptz,size float,duration interval,`

  `vorigin float=0.0,torigin timestamptz='2000-01-03') → tbox`

  If the origin of the value and/or time dimension is not specified, it is set by default to 0 and to Monday, January 3, 2000, respectively.

      SELECT getValueTile(15, 2);
      -- TBOX ([14,16))
      SELECT getTboxTimeTile('2001-01-15', interval '2 days');
      -- TBOX ([2001-01-15,2001-01-17))
      SELECT getValueTimeTile(15, '2001-01-15', 2, interval '2 days');
      -- TBOX XT([14,16),[2001-01-15,2001-01-17))
      SELECT getValueTimeTile(15, '2001-01-15', 2, interval '2 days', 1, '2001-01-02');
      -- TBOX XT([15,17),[2001-01-14,2001-01-16))

- Return the spatiotemporal tile that covers a point and/or a timestamp &Z_support;

  `getSpaceTile(point geometry,xsize float,[ysize float,zsize float],`

  `sorigin geompoint='Point(0 0 0)') → stbox`

  `getStboxTimeTile(time timestamptz,duration interval,`

  `torigin timestamptz='2000-01-03') → stbox`

  `getSpaceTimeTile(point geometry,time timestamptz,xsize float,`

  `[ysize float,zsize float,]duration,interval,sorigin geompoint='Point(0 0 0)',`

  `torigin timestamptz='2000-01-03') → stbox`

  If the origin of the space and/or time dimension is not specified, it is set by default to `Point(0 0 0)` and to Monday, January 3, 2000, respectively.

  In the case of a spatiotemporal grid, `ysize` and `zsize` are optional, the size for the missing dimensions is assumed to be equal to `xsize`. The SRID of the tile coordinates is determined by the input point and the sizes are given in the units of the SRID. If the origin for the spatial coordinates is given, which must be a point, its dimensionality and SRID should be equal to the one of box, otherwise an error is raised.

      SELECT getSpaceTile(geometry 'Point(1 1 1)', 2.0);
      -- STBOX Z((0,0,0),(2,2,2))
      SELECT getStboxTimeTile(timestamptz '2001-01-01', interval '2 days');
      -- STBOX T([2001-01-01,2001-01-03))
      SELECT getSpaceTimeTile(geometry 'Point(1 1)', '2001-01-01', 2.0, interval '2 days');
      -- STBOX XT(((0,0),(2,2)),[2001-01-01, 2001-01-03))
      SELECT getSpaceTimeTile(geometry 'Point(1 1)', '2001-01-01', 2.0, interval '2 days',
        'Point(1 1)', '2001-01-02');
      -- STBOX XT(((1,1),(3,3)),[2000-12-31, 2001-01-02))

### Bounding Box Operations

These functions fragment the bounding box of a temporal value with respect to a multidimensional grid. They provide an alternative to the functions in ttype_splitting to split the bounding boxes by specifying the maximum size of the boxes in the various dimensions.

- Return an array of value or time spans obtained from the instants or segments of a temporal number with respect to a value or time grid

  `valueBins(tnumber,vsize number,vorigin number=0) → numspan[]`

  `timeBins(temp,duration interval,torigin timestamptz='2000-01-03') → tstzspan[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. If the origin of values or time is not specified, it is set by default to 0 for value spans or to Monday, January 3, 2000 for time spans.

      SELECT valueBins(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05}', 3);
      -- {"[1, 3)","[4, 5)"}
      SELECT valueBins(tfloat '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', 3, 1);
      -- {"[1, 4)","[4, 4]"}

      SELECT timeBins(ttext '{AAA@2000-01-01, BBB@2000-01-02, AAA@2000-01-03, CCC@2000-01-04,
        AAA@2000-01-05}', '3 days');
      -- {"[2000-01-01, 2000-01-02]","[2000-01-03, 2000-01-05]"}
      SELECT timeBins(tfloat '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', '3 days', '2000-01-01');
      -- {"[2000-01-01, 2000-01-04)","[2000-01-04, 2000-01-05)"}

- Return an array of temporal boxes obtained from the instants or segments of a temporal number with respect to a value and/or time grid

  `valueBoxes(tnumber,size number,vorigin number=0) → tbox[]`

  `timeBoxes(tnumber,duration interval,torigin timestamptz='2000-01-03') → tbox[]`

  `valueTimeBoxes(tnumber,size number,duration interval,vorigin number=0,`

  `torigin timestamptz='2000-01-03') → tbox[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. If the origin of value and/or time dimension is not specified, it is set by default to 0 and to Monday, January 3, 2000, respectively.

      SELECT valueBoxes(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
      1@2000-01-05}', 3);
      /* {"TBOXINT XT([1, 3),[2000-01-01, 2000-01-05])",
          "TBOXINT XT([4, 5),[2000-01-04, 2000-01-04])"} */
      SELECT timeBoxes(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
      1@2000-01-05}', '3 days');
      /* {"TBOXINT XT([1, 3),[2000-01-01, 2000-01-02])",
          "TBOXINT XT([1, 5),[2000-01-03, 2000-01-05])"} */
      SELECT valueTimeBoxes(tint '{1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05}', 3, '3 days');
      /* {"TBOXINT XT([1, 3),[2000-01-01, 2000-01-02])",
          "TBOXINT XT([1, 2),[2000-01-03, 2000-01-05])",
          "TBOXINT XT([4, 5),[2000-01-04, 2000-01-04])"} */
      SELECT valueTimeBoxes(tfloat '[1@2000-01-01, 2@2000-01-02, 1@2000-01-03, 4@2000-01-04,
        1@2000-01-05]', 3, '3 days', 1, '2000-01-01');
      /* {"TBOXFLOAT XT([1, 4),[2000-01-01, 2000-01-04))",
          "TBOXFLOAT XT([1, 4),(2000-01-04, 2000-01-05])",
          "TBOXFLOAT XT([4, 4],[2000-01-04, 2000-01-04])"} */

- Return an array of spatiotemporal boxes obtained from the instants or segments of a temporal point with respect to a space and/or time grid &Z_support;

  `spaceBoxes(tgeompoint,xsize float,[ysize float,zsize float,]`

  `sorigin geompoint='Point(0 0 0)',borderInc bool=true) → stbox[]`

  `timeBoxes(tgeompoint,duration interval,torigin timestamptz='2000-01-03',`

  `borderInc bool=true) → stbox[]`

  `spaceTimeBoxes(tgeompoint,xsize float,[ysize float,zsize float,]duration interval,`

  `sorigin geompoint='Point(0 0 0)',torigin timestamptz='2000-01-03',`

  `borderInc bool=true) → stbox[]`

  The choice between instants or segments depends on whether the interpolation is discrete or continuous. The arguments `ysize` and `zsize` are optional, the size for the missing dimensions is assumed to be equal to `xsize`. The SRID of the tile coordinates is determined by the temporal point and the sizes are given in the units of the SRID. If the origin for the spatial coordinates is given, which must be a point, its dimensionality and SRID should be equal to the one of temporal point, otherwise an error is raised. If the origin of space and/or time dimension is not specified, it is set by default to `'Point(0 0 0)'` and to Monday, January 3, 2000, respectively. The optional argument `borderInc` states whether the upper border of the extent is included and thus, extra tiles containing the border are generated.

      SELECT spaceBoxes(tgeompoint '{Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(1 1)@2000-01-03, Point(4 4)@2000-01-04, Point(1 1)@2000-01-05}', 3);
      /* {"STBOX XT(((1,1),(2,2)),[2000-01-01, 2000-01-05])",
         "STBOX XT(((4,4),(4,4)),[2000-01-04, 2000-01-04])"} */
      SELECT timeBoxes(tgeompoint '{Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02,
        Point(1 1 1)@2000-01-03, Point(4 4 4)@2000-01-04, Point(1 1 1)@2000-01-05}',
        interval '2 days', '2000-01-01');
      /* {"STBOX ZT(((1,1,1),(2,2,2)),[2000-01-01, 2000-01-02])",
          "STBOX ZT(((1,1,1),(4,4,4)),[2000-01-03, 2000-01-04])",
          "STBOX ZT(((1,1,1),(1,1,1)),[2000-01-05, 2000-01-05])"} */
      SELECT spaceTimeBoxes(tgeompoint '{Point(1 1)@2000-01-01, Point(2 2)@2000-01-02,
        Point(1 1)@2000-01-03, Point(4 4)@2000-01-04, Point(1 1)@2000-01-05}', 3, '3 days');
      /* {"STBOX XT(((1,1),(2,2)),[2000-01-01, 2000-01-02])",
          "STBOX XT(((1,1),(1,1)),[2000-01-03, 2000-01-05])",
          "STBOX XT(((4,4),(4,4)),[2000-01-04, 2000-01-04])"} */
      SELECT spaceTimeBoxes(tgeompoint '[Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02,
        Point(1 1 1)@2000-01-03, Point(4 4 4)@2000-01-04, Point(1 1 1)@2000-01-05]',
        3, interval '3 days', 'Point(1 1 1)', '2000-01-01');
      /* {"STBOX ZT(((1,1,1),(4,4,4)),[2000-01-01, 2000-01-04))",
          "STBOX ZT(((1,1,1),(4,4,4)),(2000-01-04, 2000-01-05])",
          "STBOX ZT(((4,4,4),(4,4,4)),[2000-01-04, 2000-01-04])"} */

### Splitting Operations

These functions split a temporal value with respect to a sequence of bins (see bin_functions) or tiles (see tile_functions).

- Split a temporal number with respect to value and/or time bins &SRF;

  `valueSplit(tnumber,size number,origin number=0) → {(number,tnumber)}`

  `timeSplit(ttype,duration interval,origin timestamptz='2000-01-03') →`

  `{(time,temp)}`

  `valueTimeSplit(tnumber,size number,duration interval,vorigin number=0,`

  `torigin timestamptz='2000-01-03') → {(number,time,tnumber}`

  The result is a set of pairs or a set of triples. If the origin of the value and/or the time dimension is not specified, they are set by default to 0 and to Monday, January 3, 2000, respectively.

      SELECT (sp).number, (sp).tnumber
      FROM (SELECT valueSplit(tint '[1@2001-01-01, 2@2001-01-02, 5@2001-01-05, 10@2001-01-10]',
        2) AS sp) t;
      --  0 | {[1@2001-01-01, 1@2001-01-02)}
      --  2 | {[2@2001-01-02, 2@2001-01-05)}
      --  4 | {[5@2001-01-05, 5@2001-01-10)}
      -- 10 | {[10@2001-01-10]}
      SELECT valueSplit(tfloat '[1@2001-01-01, 10@2001-01-10)', 2.0, 1.0);
      -- (1,"{[1@2001-01-01, 3@2001-01-03)}")
      -- (3,"{[3@2001-01-03, 5@2001-01-05)}")
      -- (5,"{[5@2001-01-05, 7@2001-01-07)}")
      -- (7,"{[7@2001-01-07, 9@2001-01-09)}")
      -- (9,"{[9@2001-01-09, 10@2001-01-10 00:00:00+01)}")

      SELECT (ts).time, (ts).temp
      FROM (SELECT timeSplit(tfloat '[1@2001-02-01, 10@2001-02-10)', '2 days') AS ts) t;
      -- 2001-01-31 | [1@2001-02-01, 2@2001-02-02)
      -- 2001-02-02 | [2@2001-02-02, 4@2001-02-04)
      -- 2001-02-04 | [4@2001-02-04, 6@2001-02-06)
      -- ...
      SELECT (ts).time, astext((ts).temp) AS temp
      FROM (SELECT timeSplit(tgeompoint '[Point(1 1)@2001-02-01, Point(10 10)@2001-02-10]',
        '2 days', '2001-02-01') AS ts) AS t;
      -- 2001-02-01 | [POINT(1 1)@2001-02-01, POINT(3 3)@2001-02-03)
      -- 2001-02-03 | [POINT(3 3)@2001-02-03, POINT(5 5)@2001-02-05)
      -- 2001-02-05 | [POINT(5 5)@2001-02-05, POINT(7 7)@2001-02-07)
      -- ...

  Notice that we can split a temporal value in cyclic (instead of linear) time bins. The following two examples show how to split a temporal value by hour and by day of the week.

      SELECT (ts).time::time AS hour, merge((ts).temp) AS temp
      FROM (SELECT timeSplit(tfloat '[1@2001-01-01, 10@2001-01-03]', '1 hour') AS ts) t
      GROUP BY hour ORDER BY hour;
      /* 00:00:00 | {[1@2001-01-01 00:00:00+01, 1.1875@2001-01-01 01:00:00+01),
                     [5.5@2001-01-02 00:00:00+01, 5.6875@2001-01-02 01:00:00+01)} */
      /* 01:00:00 | {[1.1875@2001-01-01 01:00:00+01, 1.375@2001-01-01 02:00:00+01),
                     [5.6875@2001-01-02 01:00:00+01, 5.875@2001-01-02 02:00:00+01)} */
      /* 02:00:00 | {[1.375@2001-01-01 02:00:00+01, 1.5625@2001-01-01 03:00:00+01),
                     [5.875@2001-01-02 02:00:00+01, 6.0625@2001-01-02 03:00:00+01)} */
      /* 03:00:00 | {[1.5625@2001-01-01 03:00:00+01, 1.75@2001-01-01 04:00:00+01),
                     [6.0625@2001-01-02 03:00:00+01, 6.25@2001-01-02 04:00:00+01)} */
      /* ... */
      SELECT EXTRACT(DOW FROM (ts).time) AS dow_no, TO_CHAR((ts).time, 'Dy') AS dow,
        asText(round(merge((ts).temp), 2)) AS temp
      FROM (SELECT timeSplit(tgeompoint '[Point(1 1)@2001-01-01, Point(10 10)@2001-01-14)',
        '1 hour') AS ts) t
      GROUP BY dow, dow_no ORDER BY dow_no;
      /* 0 | Sun | {[POINT(1 1)@2001-01-01, POINT(1.69 1.69)@2001-01-02),
                   [POINT(5.85 5.85)@2001-01-08, POINT(6.54 6.54)@2001-01-09)} */
      /* 1 | Mon | {[POINT(1.69 1.69)@2001-01-02, POINT(2.38 2.38)@2001-01-03),
                   [POINT(6.54 6.54)@2001-01-09, POINT(7.23 7.23)@2001-01-10)} */
      /* 2 | Tue | {[POINT(2.38 2.38)@2001-01-03, POINT(3.08 3.08)@2001-01-04),
                   [POINT(7.23 7.23)@2001-01-10, POINT(7.92 7.92)@2001-01-11)} */
      /* ... */

      SELECT (sp).number, (sp).time, (sp).tnumber
      FROM (SELECT valueTimeSplit(tint '[1@2001-02-01, 2@2001-02-02, 5@2001-02-05,
        10@2001-02-10]', 5, '5 days') AS sp) t;
      --  0 | 2001-02-01 | {[1@2001-02-01, 2@2001-02-02, 2@2001-02-05)}
      --  5 | 2001-02-01 | {[5@2001-02-05, 5@2001-02-06)}
      --  5 | 2001-02-06 | {[5@2001-02-06, 5@2001-02-10)}
      -- 10 | 2001-02-06 | {[10@2001-02-10]}
      SELECT (sp).number, (sp).time, (sp).tnumber
      FROM (SELECT valueTimeSplit(tfloat '[1@2001-02-01, 10@2001-02-10)', 5.0, '5 days', 1.0,
        '2001-02-01') AS sp) t;
      -- 1 | 2001-01-01 | [1@2001-01-01, 6@2001-01-06)
      -- 6 | 2001-01-06 | [6@2001-01-06, 10@2001-01-10)

- Split a temporal point with respect to a spatial grid &Z_support; &SRF;

  `spaceSplit(tgeompoint,xsize float,[ysize float,zsize float,]`

  `origin geompoint='Point(0 0 0)',bitmatrix boolean=true,borderInc bool=true) →`

  `{(point,tpoint)}`

  `timeSplit(tpoint,duration interval,torigin timestamptz='2000-01-03') → {(time,tpoint)}`

  `spaceTimeSplit(tgeompoint,xsize float,[ysize float,zsize float,]`

  `duration interval,sorigin geompoint='Point(0 0 0)',`

  `torigin timestamptz='2000-01-03',bitmatrix boolean=true,borderInc boolean=true) →`

  `{(point,time,tpoint)}`

  The result is a set of pairs or a set of triples. If the origin of the space and/or time dimension is not specified, it is set by default to `'Point(0 0 0)'` and to Monday, January 3, 2000, respectively. The arguments `ysize` and `zsize` are optional, the size for the missing dimensions is assumed to be equal to `xsize`. If the argument `bitmatrix` is not specified, then the computation will use a bit matrix to speed up the process. The optional argument `borderInc` states whether the upper border of the extent is included and thus extra tiles containing the border are generated.

      SELECT ST_AsText((sp).point) AS point, astext((sp).tpoint) AS tpoint
      FROM (SELECT spaceSplit(tgeompoint '[Point(1 1)@2001-03-01, Point(10 10)@2001-03-10]',
        2.0) AS sp) t;
      -- POINT(0 0) | {[POINT(1 1)@2001-03-01, POINT(2 2)@2001-03-02)}
      -- POINT(2 2) | {[POINT(2 2)@2001-03-02, POINT(4 4)@2001-03-04)}
      -- POINT(4 4) | {[POINT(4 4)@2001-03-04, POINT(6 6)@2001-03-06)}
      -- ...
      SELECT ST_AsText((sp).point) AS point, astext((sp).tpoint) AS tpoint
      FROM (SELECT spaceSplit(tgeompoint '[Point(1 1 1)@2001-03-01,
        Point(10 10 10)@2001-03-10]', 2.0, geometry 'Point(1 1 1)') AS sp) t;
      -- POINT Z(1 1 1) | {[POINT Z (1 1 1)@2001-03-01, POINT Z (3 3 3)@2001-03-03)}
      -- POINT Z(3 3 3) | {[POINT Z (3 3 3)@2001-03-03, POINT Z (5 5 5)@2001-03-05)}
      -- POINT Z(5 5 5) | {[POINT Z (5 5 5)@2001-03-05, POINT Z (7 7 7)@2001-03-07)}
      -- ...

      SELECT (sp).time, astext((sp).temp) AS tpoint
      FROM (SELECT timeSplit(tgeompoint '[Point(1 1)@2001-02-01, Point(10 10)@2001-02-10]',
        interval '2 days') AS sp) t;
      -- 2001-01-31 | [POINT(1 1)@2001-02-01, POINT(2 2)@2001-02-02)
      -- 2001-02-02 | [POINT(2 2)@2001-02-02, POINT(4 4)@2001-02-04)
      -- 2001-02-04 | [POINT(4 4)@2001-02-04, POINT(6 6)@2001-02-06)
      -- ...

      SELECT ST_AsText((sp).point) AS point, (sp).time, astext((sp).tpoint) AS tpoint
      FROM (SELECT spaceTimeSplit(tgeompoint '[Point(1 1)@2001-02-01, Point(10 10)@2001-02-10]',
        2.0, interval '2 days') AS sp) t;
      -- POINT(0 0) | 2001-01-31 | {[POINT(1 1)@2001-02-01, POINT(2 2)@2001-02-02)}
      -- POINT(2 2) | 2001-01-31 | {[POINT(2 2)@2001-02-02]}
      -- POINT(2 2) | 2001-02-02 | {[POINT(2 2)@2001-02-02, POINT(4 4)@2001-02-04)}
      -- ...
      SELECT ST_AsText((sp).point) AS point, (sp).time, astext((sp).tpoint) AS tpoint
      FROM (SELECT spaceTimeSplit(tgeompoint '[Point(1 1 1)@2001-02-01,
        Point(10 10 10)@2001-02-10]', 2.0, interval '2 days', 'Point(1 1 1)',
        '2001-03-01') AS sp) t;
      -- POINT Z(1 1 1) | 2001-02-01 | {[POINT Z(1 1 1)@2001-02-01, POINT Z(3 3 3)@2001-02-03)}
      -- POINT Z(3 3 3) | 2001-02-01 | {[POINT Z(3 3 3)@2001-02-03]}
      -- POINT Z(3 3 3) | 2001-02-03 | {[POINT Z(3 3 3)@2001-02-03, POINT Z (5 5 5)@2001-02-05)}
      -- ...