Oracle_sql练习题3

本文讨论了针对员工表和部门表的多个SQL查询问题,涉及工资排名、工资比较、工作年限、员工信息关联等,展示了如何运用窗口函数和自连接等技术进行高效数据分析。
摘要由CSDN通过智能技术生成

这些题目涉及到的表通常包括:

**员工表(Employees):** 包含员工的个人信息,如姓名、工资、入职日期等。可能包括列如下:
   - employee_id
   - employee_name
   - salary
   - hire_date 
   -department_name
   - manager_id (指向上级员工的ID)

 **部门表(Departments):** 包含部门的信息,如部门名称、部门ID等。可能包括列如下:

   - department_id
   - department_name

1. **题目:** 查询每个部门中工资排名第二高的员工的姓名、工资以及部门名称。   **答案:**

   SELECT e.employee_name, e.salary, d.department_name
   FROM (
       SELECT employee_name, salary, department_id,
              ROW_NUMBER() OVER(PARTITION BY department_id ORDER BY salary DESC) AS salary_rank
       FROM employees
   ) e
   JOIN departments d ON e.department_id = d.department_id
   WHERE e.salary_rank = 2;

**思路:** 使用窗口函数 `ROW_NUMBER()` 对每个部门的员工按工资降序排列,并给每个员工分配一个排名。然后,将结果作为子查询,筛选出排名为2的员工,并通过连接部门表获取部门名称。

2. **题目:** 查询员工表中工资比其所在部门平均工资高的员工姓名、工资以及部门名称。

   **答案:**

   SELECT e.employee_name, e.salary, d.department_name
   FROM employees e
   JOIN departments d ON e.department_id = d.department_id
   JOIN (
       SELECT department_id, AVG(salary) AS avg_salary
       FROM employees
       GROUP BY department_id
   ) avg_salaries ON e.department_id = avg_salaries.department_id
   WHERE e.salary > avg_salaries.avg_salary;

   **思路:** 首先,使用子查询计算每个部门的平均工资。然后,将员工表与部门表连接,并再次连接平均工资子查询,筛选出工资高于所在部门平均工资的员工。

3. **题目:** 查询员工表中连续工作了超过5年的员工姓名、入职日期和离职日期。

   **答案:**

   SELECT employee_name, hire_date, leave_date
   FROM (
       SELECT employee_name, hire_date,
              LEAD(hire_date, 5) OVER(PARTITION BY employee_id ORDER BY hire_date) AS leave_date
       FROM employees
   ) 
   WHERE leave_date IS NOT NULL;

   **思路:** 使用窗口函数 `LEAD()` 获取每个员工的后续入职日期,然后计算出与当前入职日期相差超过5年的日期作为离职日期。

4. **题目:** 查询员工表中入职日期最晚的员工信息。

   **答案:**

   SELECT * FROM employees WHERE hire_date = (SELECT MAX(hire_date) FROM employees);

   **思路:** 使用子查询获取入职日期最晚的日期,并将其与员工表进行比较,以获取相应的员工信息。

5. **题目:** 查询员工表中任意两个员工的工资差异最大的员工姓名和工资。

   **答案:**

   SELECT e1.employee_name, e1.salary, e2.employee_name, e2.salary, ABS(e1.salary - e2.salary) AS salary_difference
   FROM employees e1
   CROSS JOIN employees e2
   WHERE e1.employee_id < e2.employee_id
   ORDER BY salary_difference DESC
   FETCH FIRST ROW ONLY;

   **思路:** 使用交叉连接 `CROSS JOIN` 获取所有员工的组合,并计算他们之间的工资差异,然后按照工资差异降序排列,选取差异最大的一组。

6. **题目:** 查询员工表中每个月入职员工的数量,并按照月份升序排列。

   **答案:**

   SELECT TO_CHAR(hire_date, 'YYYY-MM') AS hire_month, COUNT(*) AS num_employees
   FROM employees
   GROUP BY TO_CHAR(hire_date, 'YYYY-MM')
   ORDER BY hire_month;

   **思路:** 使用 `TO_CHAR()` 函数将入职日期转换为年月格式,并使用 `GROUP BY` 按照月份分组,然后计算每月入职员工的数量。

7. **题目:** 查询员工表中工资处于前20%的员工的姓名、工资以及工资百分位排名。

   **答案:**

   SELECT employee_name, salary, PERCENT_RANK() OVER (ORDER BY salary) AS salary_percent_rank
   FROM employees
   WHERE PERCENT_RANK() OVER (ORDER BY salary) <= 0.2;

   **思路:** 使用窗口函数 `PERCENT_RANK()` 计算每个员工的工资百分位排名,并筛选出排名在前20%内的员工。PERCENT_RANK()用于计算当前行的值相对于所有值的排名百分比。

8. **题目:** 查询员工表中的员工信息,如果该员工有上级,则同时显示上级的姓名。

   **答案:**

   SELECT e.employee_name, e.salary, e.manager_id, m.employee_name AS manager_name
   FROM employees e
   LEFT JOIN employees m ON e.manager_id = m.employee_id;

   **思路:** 使用自连接(self-join)将员工表与自身连接,通过匹配员工表中的 `manager_id` 字段和员工表的 `employee_id` 字段,从而获取上级的姓名。

9. **题目:** 查询员工表中入职日期早于其上级的员工信息。

   **答案:**

   SELECT e.employee_name, e.hire_date, e.manager_id
   FROM employees e
   JOIN employees m ON e.manager_id = m.employee_id
   WHERE e.hire_date < m.hire_date;

   **思路:** 使用自连接将员工表与自身连接,并通过匹配员工表中的 `manager_id` 字段和员工表的 `employee_id` 字段,然后筛选出入职日期早于上级的员工信息。

10. **题目:** 查询员工表中连续工作了不少于3年的员工的数量。   

      **答案:**

    SELECT COUNT(*) AS num_employees
    FROM (
        SELECT employee_id
        FROM employees
        GROUP BY employee_id
        HAVING MIN(hire_date) < ADD_MONTHS(SYSDATE, -36)
    ) employees_worked_3_years;

    **思路:** 使用 `GROUP BY` 子句按照员工ID分组,并使用 `HAVING` 子句筛选出至少有一次入职日期早于当前日期3年之前的员工,然后统计符合条件的员工数量。

  • 41
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值