Darbe iš nutolusių įrenginių kelis kartus per valanda surenkam įvairių meteorologinių jutiklių duomenis. Mums ganėtinai svarbu, kad įrenginys veiktų tvarkingai ir visą laiką fiksuotų realią informaciją. Žinoma, visko pasitaiko: lūžta ryšio įrenginiai ar valdikliai, dingsta elektra arba sugenda pavieniai jutikliai. Kaip identifikuoju viso įrenginio veikimą, jau esu rašęs ankščiau poste apie hierarchines SQL užklausas. Su pavienių jutiklių veikimu-neveikimu yra šiek tiek sudėtingesnė situacija. Kartais pasitaiko, kad sugedus vienam ar kitam įrenginio jutikliui, įrenginio valdiklis „užsiciklina” ir kiekvienos tolimesnės iteracijos metu gražina paskutinę iš jutiklio surinktą reikšmę, kas labai iškreipią suvokimą apie įrenginio duomenų kokybę.
Problema kaip ir aiški: norint išsiaiškinti, ar jutiklio duomenys yra „geri”, reikia tikrinti, ar duomenys iš vis yra ir ar reikšmės nesikartoja ilgą laiko periodą (pačių reikšmių teisingumas yra kitas klausimas). Norint, kad toks patikrinimas atneštų kažkokį žmogui suprantamą rezultatą, geriausia būtų identifikuoti laiko periodus (nuo-iki), kada duomenys buvo „blogi”. Tam puikiai tinka Tabibitosan metodas. Metodas leidžia labai greitai ir paprastai surasti nuoseklius duomenų intervalus.
Pavyzdžiui, turime keliolika eilučių duomenų, kuriuose skaičiai didėja su pertrūkiais (kairėje). Tabibitosan leidžia identifikuoti šiuos intervalus ir gauti gražią jų suvestinę (dešinėje):
1 2 3 5 6 7 10 11 12 20 21
MIN(NUMVAL) MAX(NUMVAL) ------------- ------------- 1 3 5 7 10 12 20 21
Smagiausia, kad užklausa yra genialiai paprasta ir lengvai suprantama:
with Ex1 as( select 1 NumVal from dual union select 2 NumVal from dual union select 3 NumVal from dual union select 5 NumVal from dual union select 6 NumVal from dual union select 7 NumVal from dual union select 10 NumVal from dual union select 11 NumVal from dual union select 12 NumVal from dual union select 20 NumVal from dual union select 21 NumVal from dual ) select min(NumVal),max(NumVal) from (select NumVal ,NumVal-Row_Number() over(order by NumVal) as disTance from Ex1) group by disTance order by min(NumVal);
Užklausos paprastumas leidžia ją pritaikyti pagal savo poreikius. Be to, užklausa veikia su bet kokio tipo duomenų intervalais ir bet kokiu stulpelių skaičiumi. Pateikiu užklausą, kurią naudoju jutiklių duomenų klaidoms aptikti:
with Ex2 as( select date'2016-08-01' DT, 1 NumVal from dual union select date'2016-08-02' DT, 2 NumVal from dual union select date'2016-08-03' DT, 1 NumVal from dual union select date'2016-08-04' DT, 3 NumVal from dual union select date'2016-08-05' DT, 4 NumVal from dual union select date'2016-08-06' DT, 1 NumVal from dual union select date'2016-08-07' DT, 0 NumVal from dual union select date'2016-08-08' DT, 0 NumVal from dual union select date'2016-08-09' DT, 0 NumVal from dual union select date'2016-08-10' DT, 0 NumVal from dual union select date'2016-08-11' DT, 0 NumVal from dual union select date'2016-08-12' DT, 1 NumVal from dual union select date'2016-08-13' DT, 2 NumVal from dual union select date'2016-08-14' DT, 3 NumVal from dual union select date'2016-08-15' DT, null NumVal from dual union select date'2016-08-16' DT, null NumVal from dual union select date'2016-08-17' DT, null NumVal from dual union select date'2016-08-18' DT, 1 NumVal from dual union select date'2016-08-19' DT, 2 NumVal from dual union select date'2016-08-20' DT, 1 NumVal from dual ) ,tabibitosan as( select NumVal, min(DT) minDT, max(DT) maxDT from (select DT,NumVal, (row_number() over (order by DT) - row_number() over (partition by NumVal order by DT) ) as disTance from Ex2) group by disTance, NumVal order by min(NumVal) ) select * from tabibitosan where maxDT - minDT > 1
Užklausa veikia analogiškai pirmajai, t. y. subužklausa „tabibitosan” ieško nuoseklių „NumVal” stulpelio reikšmių intervalo, tačiau gražina nebe patį intervalą, bet datas nuo kada iki kada tam „NumVal” tikra reikšmė nesikeitė (dešinėje).
Toks rezultatas, žinoma, yra labai painus. Atsirinkti kas ir kaip padeda paskutinė užklausos dalis, kuri gražina tik tuos laiko intervalus, kurie buvo didesni nei, šiuo atveju, viena para. Taip gaunam intervalus, kad duomenys buvo klaidingi. T. y. kur jų nebuvo arba nesikeitė pakankamai ilgą laiką: