【问题标题】:find the most early hired employees in every department [duplicate]找到每个部门中最早雇用的员工[重复]
【发布时间】:2012-01-10 18:14:12
【问题描述】:

我有以下代码用于查找每个部门中最早雇用的员工

select  d.department_name,e.first_name || ' '||  e.last_name,e.hire_date,min(e.hire_date)
      from employees e join departments d
      on e.department_id=d.department_id
   group by d.department_name,e.hire_date

但它显示了以下错误

ORA-00979: not a GROUP BY expression
00979. 00000 -  "not a GROUP BY expression"
*Cause:    
*Action:
Error at Line: 13 Column: 26

请帮我看看这段代码有什么问题?

【问题讨论】:

  • 你到底想做什么? GROUP BY 创建汇总行,但您正在尝试提取单个记录。

标签: sql oracle


【解决方案1】:
select  d.department_name,e.first_name || ' '||  e.last_name,min(e.hire_date) 
      from employees e join departments d
      on e.department_id=d.department_id
   group by d.department_name,e.first_name || ' '||  e.last_name

【讨论】:

  • 这将返回每个员工的最早雇佣日期——而不是整个部门。
【解决方案2】:

这样的查询无法工作。 为什么你按这些列分组?你想通过这样做来达到什么目的?你如何用文字来翻译查询?

在进行查询之前,请用英文写下:

最早雇用的员工是每个部门的雇用日期最短(最早)的员工。

我不打算给你查询,因为我觉得这是一个家庭作业,但你应该可以从这里下去。

【讨论】:

    【解决方案3】:

    您在分组查询中包含非聚合、非分组字段。

    此外,您按hire_date 和部门分组,因此您的查询将为每个部门内的每个不同的hire_date 返回一行,而不是每个部门只返回一行(尽管这不会停止您的查询运行,但它会阻止它返回所需的结果。)

    考虑查看子查询或分析函数以返回您需要的数据。

    【讨论】:

      【解决方案4】:

      最简单的方法通常是在这里使用分析函数。但是,如果有领带,皱纹就会出现。如果同一部门有两个人在同一天被录用,这不太可能,你想把他们两个都退回去吗?或者你想指定一个次要标准来打破平局?还是您只是希望 Oracle 随机打破平局?并且,如果您不是在寻找顶行,而是在寻找前 3 或前 5 行,那么如何处理平局之后的行。

      这个查询

      select department_name,
             employee_name,
             hire_date
        from (
          select d.department_name,
                 e.first_name || ' '||  e.last_name employee_name,
                 e.hire_date,
                 row_number() over (partition by d.department_name order by e.hire_date asc) rnk
            from employees e join departments d
              on e.department_id=d.department_id
        )
       where rnk = 1
      

      如果同一天雇用了两名员工,则将通过随机中断联系方式返回每个部门中最早 hire_date 的员工。如果您使用rankdense_rank 函数而不是row_number,则将返回两行。如果您在分析函数中向 order by 添加了附加条件,则可以确定如何打破平局(例如通过对员工的姓氏进行排序)。

      【讨论】:

        【解决方案5】:

        获得每个部门的最早雇用日期后,您可以对员工表进行内部联接,以查看您从该部门雇用了该日期的人员。

        编辑: 这样的事情应该可以工作。

        select 
            a.department_name,
            a.EarliestHireDate,
            b.first_name + ' ' + b.last_name AS EmployeeName
        from
            (
              select min(e.hire_date) as  EarliestHireDate, d.department_name, d.department_id
              from employees e join departments d
                on e.department_id=d.department_id
              group by d.department_name
            ) as a
            inner join employees as b
                on a.EarliestHireDate = b.hire_date
                    and a.department_id = b.department_id
        

        如果在该部门的最早雇用日雇用了超过 1 名员工,则每个部门将获得超过 1 名员工

        【讨论】:

        • 除了在 Oracle 中,当您创建 EmployeeName 列时,字符串连接运算符是 ||,而不是 + 之外,此方法也有效。但是,它的效率通常低于分析函数解决方案,因为它需要使用分析函数两次而不是一次访问employees 表。如果表很小,这可能不是非常重要,但如果表增长或查询被执行多次,它可能会累加。就个人而言,我也倾向于发现分析函数方法更易于阅读和维护。
        猜你喜欢
        • 2019-06-23
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 2021-01-31
        • 1970-01-01
        • 2012-10-19
        • 1970-01-01
        • 2021-12-19
        相关资源
        最近更新 更多