#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