Apply function
The Apply function queries one or more time series and applies a user-specified SQL expression or function to the selected time series elements.
Syntax
Apply(sql_express lvarchar,
ts TimeSeries, ...)
returns TimeSeries;
Apply(sql_express lvarchar,
multiset_ts multiset(TimeSeries))
returns TimeSeries;
Apply(sql_express lvarchar,
filter lvarchar,
ts TimeSeries, ...)
returns TimeSeries;
Apply(sql_express lvarchar,
filter lvarchar,
multiset_ts multiset(TimeSeries))
returns TimeSeries;
Apply(sql_express lvarchar,
begin_stamp datetime year to fraction(5),
end_stamp datetime year to fraction(5),
ts TimeSeries, ...)
returns TimeSeries with (handlesnulls);
Apply(sql_express lvarchar,
begin_stamp datetime year to fraction(5),
end_stamp datetime year to fraction(5),
multiset_ts multiset(TimeSeries))
returns TimeSeries with (handlesnulls);
Apply(sql_express lvarchar,
filter lvarchar,
begin_stamp datetime year to fraction(5),
end_stamp datetime year to fraction(5),
ts TimeSeries, ...)
returns TimeSeries with (handlesnulls);
Apply(sql_express lvarchar,
filter lvarchar,
begin_stamp datetime year to fraction(5),
end_stamp datetime year to fraction(5),
multiset_ts multiset(TimeSeries))
returns TimeSeries with (handlesnulls);
- sql_express
- The SQL expression or function to evaluate.
- filter
- The filter expression used to select time series elements.
- begin_stamp
- The begin point of the range. See Clip function for more detail about range specifications.
- end_stamp
- The end point of the range. See Clip function for more detail about range specifications.
- ts
- The first ts argument is the first series, the second ts argument is the second series, and so on. This function can take up to eight ts arguments. The order of the arguments must correspond to the desired order in the SQL expression or function. There is no limit to the number of $ parameters in the expression.
- multiset_ts
- A multiset of time series.
Description
This function runs a user-specified SQL expression on the given time series and produces a new time series containing the result of the expression at each qualifying element of the input time series.
You can qualify the elements from the input time series by specifying a time period to clip and by using a filter expression.
The sql_express argument is a comma-separated list of expressions to run for each selected element. There is no limit to the number of expressions you can run. The results of the expressions must match the corresponding columns of the result time series minus the first time stamp column. Do not specify the first time stamp as the first expression; the first time stamp is generated for each expression result.
The parameters to the expression can be an input element or any column of an input time series. Use the following format:
$ts_position.col_number
The ts_position is the position of a given time series on the input time series list. The col_number is the number of the column in the TimeSeries data type. Both the position number and column number are zero-based. For example, $0 means the element of the first input time series, $0.0 represents its time stamp column, and $0.1 is the column following the time stamp column. Another way to refer to a column is to use the column name directly, instead of the column number. Suppose the second time series has a column called high then you can use $1.high to refer to it. If the high column is the second column in the element, $1.high is equivalent to $1.1.
If the column of the input time series is a BSON column, you can specify a field with the following format:
$ts_position.bson_column_name.path.field
The ts_position is the position of a given time
series on the input time series list. You cannot specify the column number. If the BSON top-level
field name is the same as another column in the TimeSeries data type, you must include the
bson_column_name. Otherwise, omit the bson_column_name. The
path is the path to the field within the BSON document, with each part of the
path separated by a period. The field is the field name. For example,
$1.employee.id
represents the second input time series and if the TimeSeries
data type does not contain an employee column, employee.id
is processed as a
path to the value in the BSON column in the TimeSeries data type. The BSON field is
automatically cast to a FLOAT data type, however, you can explicitly cast a BSON field to an
INTEGER, BIGINT, or LVARCHAR data type. For example, you can cast the employee.id
field to an INTEGER data type: $1.employee.id::integer
. For examples, see Example: Run Apply on a BSON column.
If Apply has only one time series argument, you can refer to the column name without the time series position part; hence, $0.high is the same as $high. Notice that $0 always means the whole element of the first time series. It does not mean the first column of the time series, even if there is only one time series argument.
If you use a function as your expression, then it must take the subtype of each input time series in that order as its arguments and return a row type that corresponds to the subtype of the result time series of Apply. In most cases, it is faster to evaluate a function than to evaluate a generic expression. If performance is critical, you should implement the calculation to be performed in a function and use the function syntax. See Example: Run Apply without a filter or a clipped range for how to achieve this.
"$0.high + $1.high)/2, ($0.low + $1.low)/2"
"($0.1 + $1.1)/2, ($0.2 + $1.2)/2"
"$0.high, $1.high"
"avghigh"
"avghigh(arg1 daybar, arg2 daybar) returns (one_real)"
TRUE
are
selected."$0.vol > $1.vol and $0.close > ($0.high - $0.low)/2"
- Write a C function that creates the set and use the function as the multiset_ts argument to Apply. The C function can return the TimeSeries values in any order you want.
- Use ORDER BY in the multiset_ts expression
Apply with the multiset_ts argument evaluates the expression once for every timepoint in the resulting union of time series values. When all the data in the clipped period has been exhausted, Apply returns the resulting series.
Apply uses the optional clip time
range to restrict the data to a particular time period. If the beginning
timepoint is NULL
, then Apply uses
the earliest valid timepoint of all the input time series. If the
ending timepoint is NULL
, then Apply uses
the latest valid timepoint of all the input time series. When the
optional clip time range is not used, it is equivalent to both the
beginning and ending timepoints being NULL
: Apply considers
all elements.
If both the clip time range and filter expression are given, then clipping is done before filtering.
If you use
a string literal or NULL
for the clip time range,
you should cast to DATETIME YEAR TO FRACTION(5) on at least the beginning
timepoint to avoid ambiguity in function resolution.
When more than one input time series is specified, a union of all input time series is performed to produce the source of data to be filtered and evaluated by Apply. Hence, Apply acts as a union function, with extra filtering and manipulation of union results. For details on how the Union function works, see Union function.
Returns
A new time series with the results of evaluating the expression on every selected element from the source time series.
Example: Run Apply without a filter or a clipped range
select Apply('$high-$low',
datetime(2011-01-01) year to day,
datetime(2011-01-06) year to day,
stock_data)::TimeSeries(one_real)
from daily_stocks
where stock_name = 'IBM';
Example: Run Apply without a filter and with a clipped range
select Apply(
'($0.high+$1.high)/2, ($0.low+$1.low)/2, ($0.final+$1.final)/2,
($0.vol+$1.vol)/2',
datetime(2011-01-04) year to day,
datetime(2011-01-05) year to day,
t1.stock_data, t2.stock_data)
::TimeSeries(stock_bar)
from daily_stocks t1, daily_stocks t2
where t1.stock_name = 'IBM' and t2.stock_name = 'HWP';
Example: Create a function with a filter without a clip range
create function ts_sum(a stock_bar)
returns one_real;
return row(null::datetime year to fraction(5),
(a.high + a.low + a.final + a.vol))::one_real;
end function;
select Apply('ts_sum',
'2011-01-03 00:00:00.00000'::datetime year
to fraction(5),
'2011-01-03 00:00:00.00000'::datetime year
to fraction(5),
stock_data)::TimeSeries(one_real)
from daily_stocks
where stock_id = 901;
Example: Use a function as an expression
/* begin applyfunc.c */
#include "mi.h"
MI_ROW *
high_low_diff(MI_ROW *row, MI_FPARAM *fp)
{
MI_ROW_DESC *rowdesc;
MI_ROW *result;
void *values[2];
mi_boolean nulls[2];
mi_real *high, *low;
mi_real r;
mi_integer len;
MI_CONNECTION *conn;
mi_integer rc;
nulls[0] = MI_TRUE;
nulls[1] = MI_FALSE;
conn = mi_open(NULL,NULL,NULL);
if ((rc = mi_value(row, 1, (MI_DATUM *) &high,
&len)) == MI_ERROR)
mi_db_error_raise(conn, MI_EXCEPTION,
"ts_test_float_sql: corrupted argument row");
if (rc == MI_NULL_VALUE)
goto retisnull;
if ((rc = mi_value(row, 2, (MI_DATUM *) &low,
&len)) == MI_ERROR)
mi_db_error_raise(conn, MI_EXCEPTION,
"ts_test_float_sql: corrupted argument row");
if (rc == MI_NULL_VALUE)
goto retisnull;
r = *high - *low;
values[1] = (void *) &r;
rowdesc = mi_row_desc_create(mi_typestring_to_id(conn,
"one_real"));
result = mi_row_create(conn, rowdesc, (MI_DATUM *)
values, nulls);
mi_close(conn);
return (result);
retisnull:
mi_fp_setreturnisnull(fp, 0, MI_TRUE);
return (MI_ROW *) NULL;
}
/* end of applyfunc.c */
create function HighLowDiff(arg stock_bar) returns one_real
external name '/tmp/applyfunc.bld(high_low_diff)'
language C;
select stock_name, Apply('HighLowDiff',
stock_data)::TimeSeries(one_real)
from daily_stocks;
select stock_name, Apply('$high - $low',
stock_data)::TimeSeries(one_real)
from daily_stocks;
Example: Run Apply on a BSON column
The following statements create a time series with a BSON column, create a virtual table on the time series, and insert data into the time series:
create row type if not exists iot_row(
tstamp datetime year to fraction (5),
value bson);
Row type created.
create table if not exists cf (pid int primary key, ts timeseries(iot_row));
Table created.
EXECUTE PROCEDURE TSContainerCreate("ctn1" ,
"iot_dbs",
"iot_row",256,512);
Routine executed.
execute procedure TSCreateVirtualTab('iot_vti', 'cf', 'elem_insert');
Routine executed.
insert into cf values(1,
'origin(2016-01-01 00:00:00.00000),calendar(ts_1min),container(ctn1),
threshold(0), regular');
1 row(s) inserted.
insert into iot_vti values(1,
'2016-01-01 00:00:00.00000',
'{"outside":{"temp":21,"pressure":1003.2},"engine":{"temp":140,
"pressure":2001}}'::json::bson);
1 row(s) inserted.
insert into iot_vti values(1,
'2016-01-01 00:01:00.00000',
'{"outside":{"temp":23,"pressure":1003.2},"engine":{"temp":145,
"pressure":2020}}'::json::bson);
1 row(s) inserted.
The following statements create row data types for the output of the Apply function:
create row type if not exists apply_row(tstamp datetime year to fraction (5),
value integer);
Row type created.
create row type if not exists bson_row(tstamp datetime year to fraction (5),
value bson);
Row type created.
The following statement selects the values of the engine.pressure
field from the
BSON column:
select Apply('$0.engine.pressure::integer',
null::datetime year to fraction(5),
null::datetime year to fraction(5),
ts)::TimeSeries(apply_row)
from cf;
(expression) origin(2016-01-01 00:00:00.00000), calendar(ts_1day), container()
, threshold(0), regular, [(2001 ), (2020 )]
1 row(s) retrieved.
The following statement returns the contents of the BSON column as a BSON document:
select Apply('$0.1',
null::datetime year to fraction(5),
null::datetime year to fraction(5),
ts)::TimeSeries(bson_row)
from cf;
(expression) origin(2016-01-01 00:00:00.00000), calendar(ts_1day), container()
, threshold(0), regular, [('{"outside":{"temp":21,"pressure":1003
.2},"engine":{"temp":140,"pressure":2001}}'), ('{"outside":{"temp
":23,"pressure":1003.9},"engine":{"temp":145,"pressure":2020}}')]
1 row(s) retrieved.
The following statement returns the engine
document from the BSON column:
select Apply('$engine::bson',
null::datetime year to fraction(5),
null::datetime year to fraction(5),
ts)::TimeSeries(bson_row)
from cf;
(expression) origin(2016-01-01 00:00:00.00000), calendar(ts_1day), container()
, threshold(0), regular, [('{"engine":{"temp":140,"pressure":2001
}}'), ('{"engine":{"temp":145,"pressure":2020}}')]
1 row(s) retrieved.