Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Oracle Tutorial.docx
Скачиваний:
0
Добавлен:
24.01.2020
Размер:
401.64 Кб
Скачать

Аналитические функции.

В этой главе мы расскажем об аналитических (оконных) функциях oracle. Они позволяют в рамках одного сканирования таблицы выдать различную ценную информацию.

Cоздадим таблицу:

CREATE TABLE KK_SALARY(NAME varchar2(50), DT date, WAGE number);

Заполним ее данными:

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Иванов', to_date('01.01.2001','DD.MM.YYYY'), 1000 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Иванов', to_date('01.07.2007','DD.MM.YYYY'), 1400 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Иванов', to_date('01.08.2008','DD.MM.YYYY'), 1600 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Иванов', to_date('01.10.2010','DD.MM.YYYY'), 1500 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Петров', to_date('01.01.2004','DD.MM.YYYY'), 3000 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Петров', to_date('01.01.2005','DD.MM.YYYY'), 2500 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Петров', to_date('01.01.2010','DD.MM.YYYY'), 1700 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Петров', to_date('01.01.2011','DD.MM.YYYY'), 1400 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Рябов', to_date('15.07.2003','DD.MM.YYYY'), 15 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Рябов', to_date('21.04.2009','DD.MM.YYYY'), 1050 );

Insert into KK_SALARY (NAME, DT, WAGE) Values ('Рябов', to_date('11.01.2012','DD.MM.YYYY'), 100500 );

Отступление о Rownum.

Сначала продемонстрируем, как получать номер строки в отсортированном наборе с помощью функции rownum, которая не является аналитической функцией:

select NAME, DT, WAGE, rownum

from (select NAME, DT, WAGE from KK_SALARY order by DT)

where rownum <= 5;

Заметим, что подзапрос тут использован не зря. Именно такую конструкцию следует использовать, чтобы взять три первых записи в наборе, отсортированном по DT.

А такой запрос не гарантирует правильный результат:

select NAME, DT, WAGE from KK_SALARY where rownum <= 5 order by DT;

Rownum можно использовать, если просто в выборке нужно взять несколько первых попавшихся строк без сортировки:

select NAME, DT, WAGE from KK_SALARY where rownum <= 3;

Негрупповые аналитические функции.

Теперь познакомимся с некоторыми наиболее важными аналитическими функциями Oracle.

С помощью функции row_number мы нумеруем строки в наборе, сгруппированном по name и отсортированном по dt.

Функции max over и count over находят максимальное значение поля и количество строк в каждой группе одинаковых name.

Два варианта функции sum over находят соответственно общую сумму и сумму с нарастающим итогом по всей группе одинаковых namе.

С помощью экспоненты и логарифма можно посчитать не сумму, а произведение зарплат во всей группе одинаковых namе.

select name,

dt,

wage,

row_number() over(order by name, dt) row_number_total,

row_number() over(partition by name order by dt) row_number_for_this_name,

max(wage) over(partition by name) maximal_wage_for_this_name,

count(1) over(partition by name) count_rows_for_this_name,

sum(wage) over(partition by name) total_sum_for_this_name,

sum(wage) over(partition by name order by dt) cumulative_sum_for_this_name,

exp(sum(ln(wage)) over(partition by name)) wage_multiplicat_for_this_name

from kk_salary

order by name, dt;

Функции lag и lead позволяют взять предыдущие и следующие значения поля в отсортированном наборе:

select name,

dt,

lag(wage, 2) over(partition by name order by dt) previous_previous_wage,

lag(wage) over(partition by name order by dt) previous_wage,

wage,

lead(wage) over(partition by name order by dt) next_wage,

lead(wage, 2) over(partition by name order by dt) next_next_wage

from kk_salary

order by name, dt;

First_value и Last_value.

Теперь расскажем о негрупповых аналитических функциях first_value и last_value.

Создадим таблицу о результатах рыбной ловли:

create table fish_results(fisher_name varchar2(50), fishing_date date, fishes_catched varchar2(500));

Заполним ее данными. В дни, когда ничего не поймано, в fishes_catched проставляется NULL:

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Курилов',to_date('05.08.2012','dd.mm.yyyy'),'изысканный лосось');

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Курилов',to_date('07.08.2012','dd.mm.yyyy'),'3 изысканных лосося');

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Курилов',to_date('08.08.2012','dd.mm.yyyy'),null);

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Курилов',to_date('09.08.2012','dd.mm.yyyy'),null);

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Охотский',to_date('03.08.2012','dd.mm.yyyy'),'4 краба');

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Охотский',to_date('10.08.2012','dd.mm.yyyy'),'карп и карась');

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Сахалинов',to_date('01.08.2012','dd.mm.yyyy'),null);

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Сахалинов',to_date('02.08.2012','dd.mm.yyyy'),'2 камбалы и щука');

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Сахалинов',to_date('04.08.2012','dd.mm.yyyy'),null);

insert into fish_results(fisher_name,fishing_date,fishes_catched) values('Сахалинов',to_date('06.08.2012','dd.mm.yyyy'),'большой сом, пескарик и 5 окуней');

Продемонстрируем возможности first_value и last_value:

select fisher_name,

fishing_date,

fishes_catched,

first_value(fishes_catched) over(partition by fisher_name order by fishing_date) /*первый улов рыбака*/,

first_value(fishes_catched ignore nulls) over(partition by fisher_name order by fishing_date) /*первый непустой улов рыбака*/,

last_value(fishes_catched) over(partition by fisher_name order by fishing_date) /*последний улов рыбака на момент fishing_date*/,

last_value(fishes_catched ignore nulls) over(partition by fisher_name order by fishing_date) /*последний непустой улов рыбака на момент fishing_date*/

from fish_results

order by fisher_name, fishing_date;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]