Share via


time_weighted_avg_fl()

La funzione è una funzione time_weighted_avg_fl()definita dall'utente che calcola la media temporale ponderata di una metrica in un determinato intervallo di tempo, nei contenitori di tempo di input. Questa funzione è simile all'operatore di riepilogo. La funzione aggrega la metrica in base ai bin di tempo, ma invece di calcolare un valore medio semplice ( ) del valore della metrica in ogni bin, pesa ogni valore per la relativa durata. La durata viene definita dal timestamp del valore corrente al timestamp del valore successivo.

Questo tipo di aggregazione è necessario per i casi d'uso in cui i valori delle metriche vengono generati solo quando vengono modificati (e non in intervalli costanti). Ad esempio, in IoT, dove i dispositivi perimetrali inviano metriche al cloud solo dopo le modifiche e ottimizzare la larghezza di banda di comunicazione.

Sintassi

T | invoke time_weighted_avg_fl(t_col, y_col, key_col, stime, etime, dt)

Altre informazioni sulle convenzioni di sintassi.

Parametri

Nome Tipo Obbligatoria Descrizione
t_col string ✔️ Nome della colonna contenente il timestamp dei record.
y_col string ✔️ Nome della colonna contenente il valore della metrica dei record.
key_col string ✔️ Nome della colonna contenente la chiave di partizione dei record.
stime datetime ✔️ Ora di inizio della finestra di aggregazione.
etime datetime ✔️ Ora di fine della finestra di aggregazione.
dt timespan ✔️ Contenitore di tempo di aggregazione.

Definizione di funzione

È possibile definire la funzione incorporando il codice come funzione definita da query o creandola come funzione archiviata nel database, come segue:

Definire la funzione usando l'istruzione let seguente. Non sono necessarie autorizzazioni.

Importante

Un'istruzione let non può essere eseguita autonomamente. Deve essere seguito da un'istruzione espressione tabulare. Per eseguire un esempio funzionante di time_weighted_avg_fl(), vedere Esempio.

let time_weighted_avg_fl=(tbl:(*), t_col:string, y_col:string, key_col:string, stime:datetime, etime:datetime, dt:timespan)
{
    let tbl_ex = tbl | extend timestamp = column_ifexists(t_col, datetime(null)), value = column_ifexists(y_col, 0.0), key = column_ifexists(key_col, '');
    let gridTimes = range timestamp from stime to etime step dt | extend value=real(null), dummy=1;
    let keys = materialize(tbl_ex | summarize by key | extend dummy=1);
    gridTimes
    | join kind=fullouter keys on dummy
    | project-away dummy, dummy1
    | union tbl_ex
    | where timestamp between (stime..etime)
    | partition hint.strategy=native by key (
        order by timestamp asc, value nulls last
        | scan declare(f_value:real=0.0) with (step s: true => f_value = iff(isnull(value), s.f_value, value);)    // fill forward null values
        | extend diff_t=(next(timestamp)-timestamp)/1m
    )
    | where isnotnull(diff_t)
    | summarize tw_sum=sum(f_value*diff_t), t_sum =sum(diff_t) by bin_at(timestamp, dt, stime), key
    | where t_sum > 0
    | extend tw_avg = tw_sum/t_sum
    | project-away tw_sum, t_sum
};
// Write your query to use the function here.

Esempio

Nell'esempio seguente viene usato l'operatore invoke per eseguire la funzione.

Per usare una funzione definita da query, richiamarla dopo la definizione di funzione incorporata.

let time_weighted_avg_fl=(tbl:(*), t_col:string, y_col:string, key_col:string, stime:datetime, etime:datetime, dt:timespan)
{
    let tbl_ex = tbl | extend timestamp = column_ifexists(t_col, datetime(null)), value = column_ifexists(y_col, 0.0), key = column_ifexists(key_col, '');
    let gridTimes = range timestamp from stime to etime step dt | extend value=real(null), dummy=1;
    let keys = materialize(tbl_ex | summarize by key | extend dummy=1);
    gridTimes
    | join kind=fullouter keys on dummy
    | project-away dummy, dummy1
    | union tbl_ex
    | where timestamp between (stime..etime)
    | partition hint.strategy=native by key (
        order by timestamp asc, value nulls last
        | scan declare(f_value:real=0.0) with (step s: true => f_value = iff(isnull(value), s.f_value, value);)    // fill forward null values
        | extend diff_t=(next(timestamp)-timestamp)/1m
    )
    | where isnotnull(diff_t)
    | summarize tw_sum=sum(f_value*diff_t), t_sum =sum(diff_t) by bin_at(timestamp, dt, stime), key
    | where t_sum > 0
    | extend tw_avg = tw_sum/t_sum
    | project-away tw_sum, t_sum
};
let tbl = datatable(ts:datetime,  val:real, key:string) [
    datetime(2021-04-26 00:00), 100, 'Device1',
    datetime(2021-04-26 00:45), 200, 'Device1',
    datetime(2021-04-26 01:06), 100, 'Device1',
    datetime(2021-04-26 00:30), 400, 'Device2',
    datetime(2021-04-26 01:00), 100, 'Device2',
    datetime(2021-04-26 02:00), 300, 'Device2',
];
let minmax=materialize(tbl | summarize mint=min(ts), maxt=max(ts));
let stime=toscalar(minmax | project mint);
let etime=toscalar(minmax | project maxt);
let dt = 1h;
tbl
| invoke time_weighted_avg_fl('ts', 'val', 'key', stime, etime, dt)
| project-rename val = tw_avg
| order by key asc, timestamp asc

Output

timestamp Key Val
2021-04-26 00:00:00.0000000 Device1 125
2021-04-26 01:00:00.0000000 Device1 110
2021-04-26 00:00:00.0000000 Device2 200
2021-04-26 01:00:00.0000000 Device2 100

Il primo valore è (45m*100 + 15m*200)/60m = 125, il secondo valore è (6m200 + 54m100)/60m = 110 e così via.