【问题标题】:ORACLE SQL: Return Most recently hired employeesORACLE SQL:返回最近雇用的员工
【发布时间】:2016-07-24 18:56:56
【问题描述】:

我无法解决 Oracle SQL 的问题。我必须退回每个部门最近雇用的员工。这将需要我使用两个表:DEPARTMENTS 和 EMPLOYEES。我必须在没有硬编码的情况下解决这个问题,这意味着我不能使用 WHERE 子句,我必须使用子查询。我必须先按部门名称然后员工姓名按升序对表格进行排序。那么最终结果应该是这样的:

我认为内部连接可能会起作用,我的代码中有这个:

     SELECT d1.DEPARTMENT_ID , d1.DEPARTMENT_NAME, 
     e1.EMPLOYEES_ID,e1.EMPLOYEES_NAME, e1.JOB_TITLE, e1.JOB_TITLE
     FROM DEPARTMENTS d1
     INNER JOIN EMPLOYEES e1
     ON d1.DEPARTMENT_ID = e1.DEPARTMENT_ID
     HAVING MAX(e1.HIRE_DATE) = (SELECT e1.HIRE_DATE
                        FROM EMPLOYEES
                        GROUP BY d1.DEPARTMENT_ID)
     ORDER BY d1.DEPARTMENT_NAME, e1.EMPLOYEES_NAME ASC;

DEPARTMENTS 和 EMPLOYEES 共享 DEPARTMENT_ID 属性,因此我将它们链接在那里,但我不确定如何在最终结果中获取 e1 属性。我不断收到一些错误:

不是按表达式分组 不是单一的组功能 值太多

如果有人可以向我解释如何解决这个问题或我做错了什么,那就太好了

【问题讨论】:

  • 这是一个学校项目吗?不能使用 where 是一个奇怪的限制
  • 是的,不幸的是

标签: sql oracle subquery inner-join


【解决方案1】:

--你也可以使用rownumber

select *
from
(
SELECT d1.DEPARTMENT_ID , d1.DEPARTMENT_NAME, 
         e1.EMPLOYEES_ID,e1.EMPLOYEES_NAME, e1.JOB_TITLE, e1.JOB_TITLE,
Row_number() over (partition by d1.DEPARTMENT_ID order by hiredate desc) as rn
         FROM DEPARTMENTS d1
         INNER JOIN EMPLOYEES e1
         ON d1.DEPARTMENT_ID = e1.DEPARTMENT_ID
)
where rn=1

【讨论】:

【解决方案2】:

@TheGameiswar 给你很好的答案(使用 Row_number!),这里基于他的答案但没有WHERE,这里使用子查询:

with dep(id,name) as (select 1, 'sales' from dual union all 
                      select 2, 'develop' from dual),
     emp(id,dep_id, name, hire_date) as (select 1,1,'john',sysdate from dual union all 
                                         select 2,1,'kim', sysdate-100 from dual union all
                                         select 3,1,'kim', sysdate-101 from dual union all
                                         select 4,2,'kate', sysdate-1000 from dual union all
                                         select 5,2,'richard', sysdate-300 from dual union all
                                         select 6,2,'jack', sysdate-500 from dual)

select dep.*, emp.*
  from dep inner join 
         (select emp.*, row_number() over (partition by emp.dep_id order by hire_date desc) rn from emp) emp 
    on dep.id = emp.dep_id
    -- here no WHERE clause :)
    and emp.rn = 1

order by dep.name,emp.name

输出:

        ID NAME            ID     DEP_ID NAME    HIRE_DATE         RN
---------- ------- ---------- ---------- ------- --------- ----------
         2 develop          5          2 richard 29.09.15           1
         1 sales            1          1 john    25.07.16           1

或者你可以像这样使用双group by

with dep(id,name) as (select 1, 'sales' from dual union all 
                      select 2, 'develop' from dual),
     emp(id,dep_id, name, hire_date) as (select 1,1,'john',sysdate from dual union all 
                                         select 2,1,'kim', sysdate-100 from dual union all
                                         select 3,1,'kim', sysdate-101 from dual union all
                                         select 4,2,'kate', sysdate-1000 from dual union all
                                         select 5,2,'richard', to_date('1.07.2016','dd.mm.yyyy') from dual union all
                                         select 6,2,'richard2', to_date('1.07.2016','dd.mm.yyyy') from dual union all
                                         select 7,2,'jack', sysdate-500 from dual)

select * from dep inner join emp on dep.id = emp.dep_id
                  inner join 
              (select max(emp.id) emp_id from emp 
                      inner join (select max(hire_date) hdate from emp group by dep_id) emp_max
                         on emp.hire_date = emp_max.hdate 
                group by hdate) last_hire_emp 
  on emp.id = last_hire_emp.emp_id
order by dep.name,emp.name  

输出:

        ID NAME            ID     DEP_ID NAME     HIRE_DATE     EMP_ID
---------- ------- ---------- ---------- -------- --------- ----------
         2 develop          6          2 richard2 01.07.16           6
         1 sales            1          1 john     25.07.16           1

最后一个例子在hire_date有2个emp,在这个例子中我用max(id)获取

【讨论】:

    【解决方案3】:

    子查询的内部联接,按部门选择 max(hiredate)。

    首先,选择最长聘用日期并按部门分组。

    Select department_id, max(hiredate) hiredate
    from employees
    group by department_id
    

    现在我们将使用它作为子查询并将其与其余的员工数据进行内部连接。这里的内连接用作您的过滤器(或 where 子句)

    select (pick your fields)
    from
      (Select department_id, max(hiredate) hiredate
       from enmployees
       group by department_id) maxhire
    inner join  DEPARTMENTS d1
      on d1.department_id = maxhire.department_id
    INNER JOIN EMPLOYEES e1
      ON d1.DEPARTMENT_ID = e1.DEPARTMENT_ID
      and maxhire.hiredate = e1.hiredate
    

    如果在最近的雇用日期雇用了多人,则此方法将返回多个结果。

    【讨论】:

    • ... 或者第一个联接可能是右外部联接,以捕获没有员工的部门(在员工列中有几个空值)。这样的部门有时确实存在。
    【解决方案4】:

    所以我做了更多的计算并想出了这个:

        set linesize 200
        SELECT DEPARTMENTS.DEPARTMENT_ID AS 
        "DEPARTMENT ID",DEPARTMENTS.DEPARTMENT_NAME AS "DEPARTMENT NAME", 
        EMPLOYEES_ID AS "EMPLOYEE ID", 
        EMPLOYEES_NAME AS "EMPLOYEE NAME", MAX(HIRE_DATE) AS "HIRE DATE"
    
        FROM EMPLOYEES
    
        INNER JOIN DEPARTMENTS
    
        ON DEPARTMENTS.DEPARTMENT_ID = EMPLOYEES.DEPARTMENT_ID 
    
        GROUP BY DEPARTMENTS.DEPARTMENT_ID, 
        DEPARTMENTS.DEPARTMENT_NAME, EMPLOYEES_ID, EMPLOYEES_NAME
    
        ORDER BY DEPARTMENTS.DEPARTMENT_NAME;
    

    这一直有效,直到最近的日期成为每个部门的第一位。那么这会是子查询进入以确保每个部门名称的最大日期是最新的吗?

    【讨论】:

      猜你喜欢
      • 2022-11-14
      • 2012-01-05
      • 2014-07-29
      • 2017-06-24
      • 2022-12-19
      • 1970-01-01
      • 1970-01-01
      • 2018-01-26
      • 2021-12-09
      相关资源
      最近更新 更多