Udostępnij za pośrednictwem


time_weighted_avg_fl()

Funkcja time_weighted_avg_fl() jest funkcją zdefiniowaną przez użytkownika (UDF), która oblicza średnią ważoną czasu metryki w danym przedziale czasu z przedziałami czasu wejściowego. Ta funkcja jest podobna do operatora sumowania. Funkcja agreguje metrykę według przedziałów czasu, ale zamiast obliczać prostą średnia() wartości metryki w każdym pojemniku, waży każdą wartość według czasu trwania. Czas trwania jest definiowany ze znacznika czasu bieżącej wartości do znacznika czasu następnej wartości.

Ten typ agregacji jest wymagany w przypadkach użycia, w których wartości metryki są emitowane tylko w przypadku zmiany (a nie w stałych interwałach). Na przykład w usłudze IoT, gdzie urządzenia brzegowe wysyłają metryki do chmury tylko po zmianach i optymalizują przepustowość komunikacji.

Składnia

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

Dowiedz się więcej o konwencjach składniowych.

Parametry

Nazwa Typ Wymagane Opis
t_col string ✔️ Nazwa kolumny zawierającej sygnaturę czasową rekordów.
y_col string ✔️ Nazwa kolumny zawierającej wartość metryki rekordów.
key_col string ✔️ Nazwa kolumny zawierającej klucz partycji rekordów.
stime datetime ✔️ Godzina rozpoczęcia okna agregacji.
etime datetime ✔️ Godzina zakończenia okna agregacji.
Dt timespan ✔️ Przedział czasu agregacji.

Definicja funkcji

Funkcję można zdefiniować, osadzając kod jako funkcję zdefiniowaną przez zapytanie lub tworząc ją jako funkcję przechowywaną w bazie danych w następujący sposób:

Zdefiniuj funkcję przy użyciu następującej instrukcji let. Nie są wymagane żadne uprawnienia.

Ważne

Instrukcja let nie może być uruchamiana samodzielnie. Należy po nim wykonać instrukcję wyrażenia tabelarycznego. Aby uruchomić działający przykład programu time_weighted_avg_fl(), zobacz Przykład.

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.

Przykład

W poniższym przykładzie użyto operatora invoke do uruchomienia funkcji.

Aby użyć funkcji zdefiniowanej przez zapytanie, wywołaj ją po osadzonej definicji funkcji.

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

Dane wyjściowe

sygnatura czasowa key Val
2021-04-26 00:00:00.0000000 Urządzenie1 125
2021-04-26 01:00:00.0000000 Urządzenie1 110
2021-04-26 00:00:00.0000000 Urządzenie2 200
2021-04-26 01:00:00.0000000 Urządzenie2 100

Pierwsza wartość to (45m*100 + 15m*200)/60m = 125, druga wartość to (6m200 + 54m100)/60m = 110 itd.