Программирование >>  Преобразование значений null 

1 ... 112 113 114 [ 115 ] 116 117 118 ... 219


Теперь проект с PROJ ID 4 включен в окончательное результирующее множество, и только проект с PROJ ID 5 не вошел в него. Применяя эти рецепты в своем коде, внимательно изучайте предъявляемые требования.

Вычисление разности между значениями строк одной группы или сегмента

Задача

Требуется выбрать для каждого служащего DEPTNO, ENAME и SAL, а также найти разность между значениями SAL для служащих одного отдела (т. е. для служащих с одинаковыми значениями DEPTNO). Разность должна вычисляться между каждым служащим и служащим, который был принят на работу сразу после него (необходимо выяснить, есть ли зависимость между стажем работы и заработной платой для каждого отдела). Для служащих, которые были приняты на работу позже всех в своих отделах, возвращается значение N/A . Должно быть получено следующее результирующее множество:

DEPTNO

ENAME

HIREDATE

DIFF

CLARK

2450

09-JUN-1981

-2550

KING

5000

17-NOV-1981

3700

MILLER

1300

23-JAN-1982

SMITH

17-DEC-1980

-2175

JONES

2975

02-APR-1981

FORD

3000

03-DEC-1981

SCOTT

3000

09-DEC-1982

1900

ADAMS

1100

12-JAN-1983

ALLEN

1600

20-FEB-1981

WARD

1250

22-FEB-1981

-1600

BLAKE

2850

01-MAY-1981

1350

TURNER

1500

08-SEP-1981

MARTIN

1250

28-SEP-1981

JAMES

03-DEC-1981

Решение

Данная задача - еще один пример, когда пригодятся оконные функ-ции1 Oracle LEAD OVER и LAG OVER. Они обеспечивают возможность доступа к последующей и предыдущей строкам без дополнительных объединений. Для остальных СУБД можно использовать скалярные подзапросы, хотя они усложняют решение. Эта конкретная задача теряет всю свою прелесть, когда приходится решать ее с помощью скалярных подзапросов и рефлексивных объединений.

В документации по Oracle эти функции также называются аналитическими. - Примеч. науч. ред.



DB2, MySQL, PostgreSQL и SQL Server

Для получения значения HIREDATE для служащего, принятого на работу следующим после рассматриваемого служащего, используйте скалярный подзапрос. Затем с помощью другого скалярного подзапроса найдите его заработную плату:

1 select deptno,ename,hiredate,sal,

2 coalesce(cast(sal-next sal as char(10)),N/A) as diff

3 from (

4 select e.deptno,

5 e.ename,

6 e.hiredate,

7 e.sal,

8 (select min(sal) from emp d

9 where d.deptno=e.deptno

10 and d.hiredate =

11 (select min(hiredate) from emp d

12 where e.deptno=d.deptno

13 and d.hiredate > e.hiredate)) as next sal

14 from emp e

15 ) x

Oracle

Чтобы получить заработную плату служащего, следующего по отношению к текущей строке, используйте оконную функцию LEAD OVER:

1 select deptno,ename,sal,hiredate,

2 lpad(nvl(to char(sal-next sal),N/A),10) diff

3 from (

4 select deptno,ename,sal,hiredate,

5 lead(sal)over(partition by deptno

6 order by hiredate) next sal

7 from emp

Обсуждение

DB2, MySQL, PostgreSQL и SQL Server

Первый шаг - с помощью скалярного подзапроса найти значение HIRE-DATE служащего, принятого на работу в тот же отдел сразу после рассматриваемого служащего. В скалярном подзапросе используется функция MIN(HIREDATE), которая обеспечивает возвращение только одного значения, даже если в один день было нанято несколько человек:

select e.deptno, e.ename, e.hiredate, e.sal,

(select min(hiredate) from emp d where e.deptno=d.deptno



and d.hiredate > e.hiredate) as next hire

from

emp e

order

by 1

DEPTNO

ENAME

HIREDATE

NEXT HIRE

CLARK

09-JUN-1981

2450

17-NOV-1981

KING

17-NOV-1981

5000

23-JAN-1982

MILLER

23-JAN-1982

1300

SMITH

17-DEC-1980

02-APR-1981

ADAMS

12-JAN-1983

1100

FORD

03-DEC-1981

3000

09-DEC-1982

SCOTT

09-DEC-1982

3000

12-JAN-1983

JONES

02-APR-1981

2975

03-DEC-1981

ALLEN

20-FEB-1981

1600

22-FEB-1981

BLAKE

01-MAY-1981

2850

08-SEP-1981

MARTIN

28-SEP-1981

1250

03-DEC-1981

JAMES

03-DEC-1981

TURNER

08-SEP-1981

1500

28-SEP-1981

WARD

22-FEB-1981

1250

01-MAY-1981

Следующий шаг - с помощью другого скалярного подзапроса найти заработную плату служащего, принятого на работу в день, соответствующий дате NEXT HIRE. Опять же в решении используется функция MIN, что гарантирует возвращение одного значения:

select e.deptno, e.ename, e.hiredate, e.sal,

(select min(sal) from emp d where d.deptno=e.deptno and d.hiredate =

(select min(hiredate) from emp d where e.deptno=d.deptno

and d.hiredate > e.hiredate)) as next sal

from emp e order by 1

DEPTNO ENAME

HIREDATE

SAL NEXT SAL

CLARK

09-JUN-1981

2450

5000

KING

17-NOV-1981

5000

1300

MILLER

23-JAN-1982

1300

SMITH

17-DEC-1980

2975

ADAMS

12-JAN-1983

1100

FORD

03-DEC-1981

3000

3000

SCOTT

09-DEC-1982

3000

1100

JONES

02-APR-1981

2975

3000

ALLEN

20-FEB-1981

1600

1250

BLAKE

01-MAY-1981

2850

1500

MARTIN

28-SEP-1981

1250



1 ... 112 113 114 [ 115 ] 116 117 118 ... 219

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика