【问题标题】:obtain the employee names who made a higher salary in March 2018 than their average monthly salary for all previous months获取 2018 年 3 月工资高于其历年平均月工资的员工姓名
【发布时间】:2022-10-04 16:29:40
【问题描述】:

从emp1中选择*;

EMP_ID FIRST_NAME LAST_NAME

10100 马科斯·比塞特

10101 凯特佩雷斯

10102 卡洛斯卡斯科

从付款历史中选择 *;

EMP_ID PAY_TYPE AMT_PAID PAY_DATED

10100 月薪 12000 02-FEB-18

10101 月薪 2800 02-FEB-18

10102 月薪 1900 02-MAR-18

10101 奖金 1500 08-MAR-18

10102 调整 124 10-MAR-18

请使用With Clause给出答案(我从互联网上得到了这个问题..但我无法解决这个问题

【问题讨论】:

  • 你没有问过问题。您实际上遇到问题的是任务的哪一部分?你试过什么?你到底卡在哪里了?展示您的方法,并告诉我们您需要帮助的地方。
  • 请澄清您的具体问题或提供其他详细信息以准确突出您的需求。正如它目前所写的那样,很难准确地说出你在问什么。

标签: sql oracle plsql


【解决方案1】:

这是一个选项,一步一步。在代码中读取 cmets。

with 
avg_sal as
  -- average salary per each employee
  (select emp_id, 
          avg(amt_paid) avg_sal
   from payment_history
   group by emp_id
  ),
march_sal as
  -- salary employee earned in March 2018
  (select emp_id, 
          amt_paid
   from payment_history
   where to_char(pay_dated, 'yyyymm') = '201803'
  )
select e.first_name
from emp1 e join avg_sal a on a.emp_id = e.emp_id
            join march_sal m on m.emp_id = e.emp_id
where m.amt_paid > a.avg_sal;

如果pay_dated 列上有索引,则march_sal CTE 中的WHERE 子句可能需要重写,因为将to_char 函数应用于它(列)将不会使用该索引。在这种情况下,你会使用

WHERE pay_dated >= date '2018-03-01'
  AND pay_dated <  date '2018-04-01'

另一方面,您可能在 to_char(pay_dated, 'yyyymm') 上有一个基于函数的索引 - 在这种情况下,请保留它原样.

【讨论】:

  • 伟大的 !!!太感谢楼主了。。。。。。
  • @AbinashMandal问题是“......比他们之前所有月份的平均月薪”,而这将其与“他们所有月份的平均月薪”进行比较。您需要平均添加一个WHERE 过滤器。
  • 您能否建议在哪里阅读有关 with 子句的所有内容,或者如果您有自己的博客,那么您可以附加任何链接....
【解决方案2】:

要找到 3 月份的工资和以前的平均工资,您可以将每个员工和月份的工资相加,然后使用条件聚合:

SELECT MAX(e.first_name) AS first_name,
       MAX(e.last_name) AS last_name,
       SUM(CASE WHEN month = DATE '2018-03-01' THEN pay END) AS march_pay,
       AVG(CASE WHEN month < DATE '2018-03-01' THEN pay END) AS avg_previous_pay
FROM   emp1 e
       INNER JOIN (
         SELECT emp_id,
                TRUNC(pay_dated, 'MM') AS month,
                SUM(amt_paid) AS pay
         FROM   payment_history
         GROUP BY emp_id,
                TRUNC(pay_dated, 'MM')
       ) p
       ON e.emp_id = p.emp_id
GROUP BY e.emp_id

其中,对于样本数据:

CREATE TABLE emp1 (EMP_ID, FIRST_NAME, LAST_NAME) AS
SELECT 10100, 'Marcos', 'Bisset' FROM DUAL UNION ALL
SELECT 10101, 'Kate',   'Perez'  FROM DUAL UNION ALL
SELECT 10102, 'Carlos', 'Casco'  FROM DUAL;

CREATE TABLE payment_history (EMP_ID, PAY_TYPE, AMT_PAID, PAY_DATED) AS
SELECT 10100, 'monthly pay', 12000, DATE '2018-02-02' FROM DUAL UNION ALL
SELECT 10101, 'monthly pay',  2800, DATE '2018-02-02' FROM DUAL UNION ALL
SELECT 10102, 'monthly pay',  1900, DATE '2018-03-02' FROM DUAL UNION ALL
SELECT 10101, 'bonus',        1500, DATE '2018-03-08' FROM DUAL UNION ALL
SELECT 10102, 'adjustment',    124, DATE '2018-03-10' FROM DUAL;

输出:

FIRST_NAME LAST_NAME MARCH_PAY AVG_PREVIOUS_PAY
Marcos Bisset null 12000
Kate Perez 1500 2800
Carlos Casco 2024 null

然后要找到三月份工资高于之前平均工资的员工,您可以使用HAVING 子句:

SELECT MAX(e.first_name) AS first_name,
       MAX(e.last_name) AS last_name
FROM   emp1 e
       INNER JOIN (
         SELECT emp_id,
                TRUNC(pay_dated, 'MM') AS month,
                SUM(amt_paid) AS pay
         FROM   payment_history
         GROUP BY emp_id,
                TRUNC(pay_dated, 'MM')
       ) p
       ON e.emp_id = p.emp_id
GROUP BY e.emp_id
HAVING SUM(CASE WHEN month = DATE '2018-03-01' THEN pay END)
        > AVG(CASE WHEN month < DATE '2018-03-01' THEN pay END)

正如您从之前的数据中看到的那样,它没有输出任何行,员工要么有更高的平均之前工资,要么他们在其中一个月份没有工资;要获得结果,您需要一个更大的数据集,其中有一行实际符合要求。

fiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-16
    • 2020-08-09
    • 2019-01-25
    • 2012-08-02
    • 2019-03-24
    • 2011-04-28
    • 2022-01-22
    • 1970-01-01
    相关资源
    最近更新 更多