PL SQL: функции на отметку времени - PullRequest
0 голосов
/ 17 февраля 2011

У меня есть таблица из 16 столбцов, тогда как первый столбец - это отметка времени (т.е. 16/02/2011 00:00:00), и таблица заполнена 5-минутными измерениями, что означает, что будет 288 5-минутных измерений на столбец и дату.Если я хочу посчитать, скажем, значения столбца «RTTD», которые превышают> 100 мс каждый день и каждый месяц, каково решение?

Ответы [ 2 ]

3 голосов
/ 23 февраля 2011

Я создал простую таблицу (мне не надоели все шестнадцать столбцов):

SQL> desc t23
 Name                    Null?    Type
 ----------------------- -------- -----------------
 TS                               TIMESTAMP(6)
 RTTD                             NUMBER
 STN_ID                           NUMBER

SQL>

Этот шаткий анонимный блок генерирует четыре дня чтения для четырех станций:

declare
    dt timestamp := trunc(systimestamp, 'MM');
begin

    for r in 1..1152 loop
        insert into t23 values (dt, round(dbms_random.value(0,120)), 11);
        insert into t23 values (dt, round(dbms_random.value(0,120)), 22);
        insert into t23 values (dt, round(dbms_random.value(0,99)), 33);
        if r < 600 then
            insert into t23 values (dt, round(dbms_random.value(0,120)), 44);
        else
            insert into t23 values (dt, round(dbms_random.value(0,80)), 44);
        end if;
        dt := dt + interval '5' minute;
            end loop;
end;
/

Таким образом, этот запрос будет суммировать показания для четырех станций за четыре дня. COUNT() игнорирует значения NULL, а SELECT использует это: CASE() возвращает ноль для любого значения RTTD меньше 100.

SQL> select trunc(ts) as dt
  2         , stn_id
  3         , count(*) as tot_reads
  4         , count(case when rttd >= 100 then rttd else null end) as rttd_100
  5  from t23
  6  group by trunc(ts), stn_id
  7  order by 1, 2
  8  /

DT            STN_ID  TOT_READS   RTTD_100
--------- ---------- ---------- ----------
01-FEB-11         11        288         35
01-FEB-11         22        288         51
01-FEB-11         33        288          0
01-FEB-11         44        288         54
02-FEB-11         11        288         52
02-FEB-11         22        288         48
02-FEB-11         33        288          0
02-FEB-11         44        288         53
03-FEB-11         11        288         51
03-FEB-11         22        288         43
03-FEB-11         33        288          0
03-FEB-11         44        288          2
04-FEB-11         11        288         48
04-FEB-11         22        288         45
04-FEB-11         33        288          0
04-FEB-11         44        288          0

16 rows selected.

SQL>

Чтобы агрегировать это по месяцам, вам просто нужно заменить TRUNC(ts) на TRUNC(ts, 'MM'), который работает так:

SQL> select systimestamp as now
  2         , trunc(systimestamp) as today
  3         , trunc(systimestamp, 'MM') as fom
  4  from dual
  5  /

NOW                                  TODAY     FOM
------------------------------------ --------- ---------
23-FEB-11 11.39.29.127000 +00:00     23-FEB-11 01-FEB-11

SQL>
1 голос
/ 17 февраля 2011

Не уверен, что именно вы хотите. Определение проблемы слишком расплывчато, и я не уверен, какова именно та таблица, о которой вы говорите ...

Во всяком случае, я думаю, это было бы что-то вроде этого:

SELECT
    EXTRACT(YEAR FROM FIRST_COLUMN) AS YEAR_,
    EXTRACT(MONTH FROM FIRST_COLUMN) AS MONTH_,
    EXTRACT(DAY FROM FIRST_COLUMN) AS DAY_,
    COUNT(*) AS TOTAL
FROM
    SOME_TABLE
WHERE
    RTTD > 100
GROUP BY
    EXTRACT(YEAR FROM FIRST_COLUMN),
    EXTRACT(MONTH FROM FIRST_COLUMN),
    EXTRACT(DAY FROM FIRST_COLUMN),
...