Рост заработной платы между двумя последними датами

#sql #postgresql #date

#sql #postgresql #Дата

Вопрос:

Я пытаюсь решить этот вопрос :

  • Найдите рост (в процентах) зарплаты между двумя последними датами, ближайшими к текущему моменту, и ранжируйте результат по росту на одного сотрудника.

Я пробовал это :

 SELECT employee, salary AS second_salary
FROM salary
INNER JOIN salary sal
ON (sal.paydate = (SELECT salary FROM salary WHERE paydate = (SELECT MAX(paydate) FROM salary)) AND sal.employee = salary.employee)
WHERE date = (
    SELECT MAX(paydate) FROM salary WHERE paydate <> (
        SELECT MAX(paydate) FROM salary))
  

Но это не работает

 |  paydate   | salary | employee  |
|------------|--------|-----------|
| 2015-05-15 |   1000 |         1 |
| 2015-04-15 |   1250 |         1 |
| 2015-03-15 |    800 |         1 |
| 2015-02-15 |   3000 |         1 |
| 2015-05-15 |    500 |         2 |
| 2015-04-15 |   1500 |         2 |
| 2015-03-15 |   2500 |         2 |
| 2015-02-15 |   3000 |         2 |
| 2015-05-15 |    400 |         3 |
| 2015-04-15 |    582 |         3 |
| 2015-03-15 |    123 |         3 |
| 2015-02-15 |    659 |         3 |
  

Я хочу получить рост в процентах между двумя последними зарплатами, ранжированными по росту.

Ответ №1:

Во-первых: я рекомендую вам прочитать то, что есть в документации postgresql о функциях окон. (https://www.postgresql.org/docs/current/tutorial-window.html )

Второе: Вот другая версия кода, которая работает либо :

 with cte as
(
    select 
        *
        , dense_rank() over (order by paydate desc) as ranker
        , lag(salary) over (partition by employee order by paydate desc) as previous_salary
    from salary
)
select 
    employee
    , cast(((salary - previous_salary) * 100) / previous_salary as varchar)||' %' as PayGrowth
    --, * -- uncomment if you want to understand a little better the window mechanism.
from cte
where ranker = 2
order by employee, paydate;
  

Результат :

 employee  PayGrowth
1         25 %
2         200 %
3         45 %
  

Ответ №2:

Я использовал оконные функции RANK () и LEAD () во вложенном запросе, чтобы получить изменение и индекс для изменения, а затем выбрал последнее изменение в основном запросе для каждого сотрудника

 SELECT employee, paydate, change
FROM (
    SELECT employee, paydate,
        RANK() OVER (PARTITION BY employee ORDER BY paydate DESC) as rnk,
        (salary - LEAD(salary) OVER (PARTITION BY employee ORDER BY paydate DESC)) * 100.0 / salary as change
    FROM salary) w
WHERE rnk = 1
ORDER BY change DESC
  

Вывод

 employee    paydate     change
1           2015-05-15  -25.0000000000000000
3           2015-05-15  -45.5000000000000000
2           2015-05-15  -200.0000000000000000
  

Комментарии:

1. Спасибо. Мне нужно немного изменить его, чтобы возвращать проценты именно так, как я хочу : SELECT employee, paydate, change FROM ( SELECT employee, paydate, RANK() OVER (PARTITION BY employee ORDER BY paydate DESC) as rnk, (salary / NULLIF((LEAD(salary) OVER (PARTITION BY employee ORDER BY paydate DESC)), 0) - 1) * 100 / salary as change FROM salary) w WHERE rnk = 1 ORDER BY change DESC

Ответ №3:

Вы можете использовать lag аналитическую функцию Windows

 with salary( paydate, salary, employee) as
(    
 select '2015-05-15',1800,1  union all
 select '2015-04-15',1600,1  union all
 select '2015-03-15',1300,1  union all   
 select '2015-02-15',1000,1  
)    
select s.paydate,s.salary, 
       round(100*(cast(s.salary-lag(s.salary,1,s.salary) 
                  over (partition by s.employee order by s.paydate) as decimal)
             /lag(s.salary,1,s.salary) over (partition by s.employee order by s.paydate)
              ,2) as growth_as_percentage  
  from salary s
 order by s.employee, s.paydate desc;

paydate     salary  growth_as_percentage
2015-05-15  1800    12,5000
2015-04-15  1600    23,0800
2015-03-15  1300    30
2015-02-15  1000    0 
  

Demo