我有一个查询,该查询将显示2年内(如果有3年)过去的3个薪水。我已经查询并运行了,问题是,它的运行速度非常慢...我想知道是否有编写此查询的更好方法。我是oracle的新手。
这是我的桌子
TABLE 1: Salary
ASSIGN_ID | start_date | end_date | salary |
1 | 11/27/2017 | 1/05/2018 | 50000.0 |
2 | 1/06/2018 | 6/08/2018 | 76000.0 |
3 | 6/09/2018 | 12/31/4712 | 80500.0 |
TABLE 2: Assignments
ASSIGN_ID | per_ID | start_date | end_date |
1 | 1 | 11/2/2017 | 1/05/2018 |
2 | 1 | 1/06/2018 | 6/08/2018 |
3 | 1 | 6/09/2018 | 12/31/4712 |
4 | 2 | 5/12/2016 | 7/18/2017 |
5 | 2 | 7/19/2017 | 12/31/4712 |
Table 3: Person
per_id | first_name | last_name |
1 | John | Smith |
2 | Jane | Doe |
如果结束日期当前在任务中处于活动状态,则默认为12/31/4712
我的查询如下:
SELECT
per.first_name,
per.last_name,
(CASE WHEN sal1.start_date >= add_months(CURRENT_DATE, -24)
THEN sal1.salary
ELSE NULL END) oldest_salary,
(CASE WHEN sal2.start_date >= add_months(CURRENT_DATE, -24)
THEN sal2.salary
ELSE NULL END) prior_salary,
sal3.salary current_salary,
FROM
person per
INNER JOIN assignments asg1 ON asg1.per_id = per.per_id
INNER JOIN assignments asg2 ON asg2.per_id = asg1.per_id
INNER JOIN assignments asg3 ON asg3.per_id = asg2.per_id
INNER JOIN salary sal1 ON sal1.assign_id = asg1.assign_id
INNER JOIN salary sal2 ON sal2.assign_id = asg2.assign_id
INNER JOIN salary sal3 ON sal3.assign_id = asg3.assign_id
WHERE asg3.start_date =
(SELECT MAX(asg.start_date
FROM assignments asg
WHERE asg.assign_id = asg3.assign_id)
AND (asg3.start_date - 1) BETWEEN asg2.start_date and asg2.end_date
AND (asg2.start_date - 1) BETWEEN asg1.start_date and asg1.end_date
AND sal1.salary != sal2.salary
AND sal2.salary != sal3.salary
ORDER BY 2,1
有没有更简单的方法来做到这一点?因为当我运行脚本时,它将永远处理。我想我可能需要更好的加入。就像我说的我是新手一样,对联接的理解也很薄弱。
答案 0 :(得分:1)
一种简单的形式:
SELECT
z.first_name,
z.last_name,
--typical cross-db compatible pivot method
MAX(CASE WHEN z.rown = 1 THEN z.salary END) as recentsalary,
MAX(CASE WHEN z.rown = 2 THEN z.salary END) as oldersalary,
MAX(CASE WHEN z.rown = 3 THEN z.salary END) as oldestsalary
FROM
(
SELECT
per.first_name,
per.last_name,
--number assignments from 1=recent to N older
row_number() over(partition by a.per_id order by a.start_date desc) rown
s.salary
FROM --join up all
person p
INNER JOIN assignments a ON a.per_id = p.per_id
INNER JOIN salary s ON s.assign_id = s.assign_id
WHERE a.end_date > ADD_MONTHS(SYSDATE, -36) --only recent 3 years
) z
WHERE z.rown <= 3 --only the most recent 3 assignments
GROUP BY first_name, last_name --achieve pivot
它的工作原理是:
汇总所有数据,以便了解人员,任务和薪水
仅考虑3年前结束的任务
按从小到大的顺序编号作业(1 =最小)
将每人最近,最老和最老的薪水最高的3个编号分为3列