从过去 2 年中选择 3 个薪水的优化查询

Optimized Query that selects 3 salaries from the past 2 years

我有一个查询将显示过去 2 年内的 3 个薪水(如果有 3 个)我有查询,运行问题是,它非常慢......我想知道是否有更好的方法来编写此查询。我对甲骨文有些陌生。

这是我的表格

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

有更简单的方法吗?因为当我 运行 我的脚本时,它会永远处理。我想我可能需要更好的加入。就像我说的,我是新手,我对连接的理解很薄弱。

更简单的形式:

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 列,表示每人的最近、较早和最早的工资