Повышение зарплаты на 15% с использованием только SQL? - PullRequest
0 голосов
/ 19 февраля 2012

Я пытаюсь изменить схему SCOTT, увеличив зарплату сотрудников на 15%. Если получающаяся зарплата превышает его или ее максимально возможную зарплату, HISAL, в SALGRADE мы просто используем HISAL, мой код:

select 
  coalesce((
    select   sal*1.15 
    from emp , salgrade  
    where 
      sal*1.15<=hisal
   ) , 
   (select hisal from emp ,salgrade where sal*1.15>hisal )) raised_sal
from emp ;

Внутренний выбор возвращает несколько строк

У кого-нибудь есть предложения или другой код?

Ответы [ 3 ]

3 голосов
/ 19 февраля 2012

Если мы разбиваем то, что вы пытаетесь сделать:

coalesce дает первое значение, если оно не равно нулю, затем второе и т. Д. Вы не указали никаких условий соединения, поэтому выВы делаете cartesian join между emp и salgrade.Это вернет количество строк в emp , умноженное на количество строк в salgrade;при условии вашего условия соединения.

Вторая часть вашего запроса делает то же самое в обратном направлении.

Предполагая, что table_structure:

create table emp (
        emp_id number
      , salary number -- current salary
      , salgrade_id number -- current salary grade 
      , dept_id -- current department
         );

create table salgrade (
      , salgrade_id number
      , hisal number -- max salary for that grade
       );

Вы хотитеделать что-то вроде этого:

select least( e.salary * 1.15, s.hisal )
  from emp e
  join salgrade s
    on e.salgrade_id = s.salgrade_id

Функция least аналогична min;в том, что он будет принимать минимальное значение.Однако он работает с несколькими столбцами в одной строке, а не с несколькими строками в одном столбце.

Принимая значения least из hisal и salary * 1.15, мы гарантируем, что при увеличении зарплаты будет большечем hisal, то вместо этого берется hisal.

В этом случае join означает, что для каждого emp_id мы берем hisal для соответствующего уровня заработной платы.Я бы настоятельно рекомендовал читать о соединениях SQL - эта ссылка была 7-й в Google, что было немного удивительно (Джефф, кажется, везде), но это довольно хорошо и имеет много других ссылок.

Чтобы изменить запрос, чтобы вы могли выполнять его для всех сотрудников, зарабатывающих более 100 000 (богатые становятся богаче), это выглядело бы примерно так:

select least( e.salary * 1.15, s.hisal )
  from emp e
  join salgrade s
    on e.salgrade_id = s.salgrade_id
 where e.salary > 100000

Или усложнять ситуацию, если вы хотитесделайте это только для ИТ-специалистов (почему бы и нет), вы можете расширить это на что-то вроде этого:

select least( e.salary * 1.15, s.hisal )
  from emp e
  join salgrade s
    on e.salgrade_id = s.salgrade_id
  join dept d
    on e.dept_id = d.dept_id
 where d.dept = 'IT' 

Эти объединения, будучи inner joins в отличие от outer joins (обычно left outer joins - см.ссылка) подразумевает, что каждый сотрудник имеет оценку и отдел.

1 голос
/ 19 февраля 2012

Вы должны присоединиться к emp с salgrade через non equijoin :

    select   sal*1.15 
    from 
      emp 
        inner join
      salgrade sg
        on emp.sal BETWEEN sg.losal AND sg.hisal  <-- here!
    where 
      sal*1.15<=hisal

Дополнительная информация: Введение в базовый SQL, часть 3 - Сложные объединения и подзапросы :

"мы присоединились с помощью оператора BETWEEN. Зоны выплат в SALGRADE В таблице используется диапазон окладов для обозначения оценки. "

EDIT

Чтобы рассчитать оценку сотрудника, вы должны посмотреть на зарплату сотрудника и посмотреть на зарплату для диапазона зарплаты, который содержит зарплату сотрудника.

Это оценочные данные:

...
INSERT INTO SALGRADE VALUES (2,1201,1400);
INSERT INTO SALGRADE VALUES (3,1401,2000);
...

Если зарплата сотрудника равна 1495, это означает, что его оценка равна 2.

Если вы увеличиваете 1395 на 15%, то это выходит за пределы вашего диапазона, и, как вы объясняете, вы должны установить зарплату в 1400, что является исцелением для диапазона 2.

Ваш запрос:

select 
  coalesce((
    select   sal*1.15 
    from emp e2
    inner join
       salgrade sg
            on e2.sal BETWEEN sg.losal AND sg.hisal
    where 
      e2.EMPNO = e1.EMPNO and
      sal*1.15<=hisal
   ) , 
   (select hisal from emp e2 inner join salgrade sg
    on e2.sal BETWEEN sg.losal AND sg.hisal
    where e2.EMPNO = e1.EMPNO 
   )) raised_sal
from emp e1 ;

Без подзапросов:

select 
   case 
     when sal*1.15  < hisal then sal*1.15 
     when sal*1.15  >= hisal then hisal
   end
   raised_sal
from 
   emp e1 
     inner join
   salgrade sg
     on e1.sal BETWEEN sg.losal AND sg.hisal

Отказ от ответственности, не тестировался.

0 голосов
/ 19 февраля 2012

Я думаю, что вы пропустили только условие соединения ...

в обоих запросах вы можете указать условие соединения, если оно есть (например, emp.employee_name = salgrade.employee_name)

и должныдать внутреннее условие запроса также ... как

select 
  coalesce((
    select   sal*1.15 
    from emp e2, salgrade  
    where 
      sal*1.15<=hisal
and e2.employee_name = e1.employee_name
   ) , 
   (select hisal from emp e3,salgrade where sal*1.15>hisal 
and e3.employee_name = e1.emplyee_name
)) raised_sal
from emp e1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...