连接列并根据连接的结果对它们进行分组

时间:2015-02-19 16:05:35

标签: sql database oracle

我有一张表格,显示员工的部门和职位以及职位的最后更新。我的目标是列出每个部门中每个部门的最新职位(每个部门的MAX last_update)。但问题是我无法连接两个列并通过此连接将它们分组。

例如,表格是

Departement    Position      employee       last_update    
dep1              pos1       employee1          16:00
dep1              pos2       employee1          08:00
dep1              pos3       employee1          11:00   
dep2              pos4       employee2          13:00
dep2              pos5       employee2          09:00
dep2              pos6       employee3          07:00

期望的结果应该是:

Departement    Position      employee       last_update    
dep1              pos1       employee1          16:00
dep2              pos4       employee2          13:00
dep2              pos6       employee3          07:00

我必须连接员工和他的部门,并按部门和员工的姓名对他们进行分组以获得结果。 但是我不能用oracle这样的小组进行连接:

SELECT t.department, t.position,concat(t.department,t.employee), t.employee , r.MaxTime
FROM (SELECT department,position,employee, MAX(last_update) as MaxTime
  FROM employeetable
  GROUP BY (concat(department,employee))) r
  INNER JOIN employeetable t ON t.departement = r.department AND t.last_update = r.MaxTime

非常感谢

4 个答案:

答案 0 :(得分:1)

为什么要尝试按两列的串联进行分组而不仅仅是两列本身?另外,last_update列的数据类型是什么?我真诚地希望它是DATETIMESTAMP。话虽如此,您正在尝试做什么 - 找到每个部门和员工的最新行?如果是这样,那么就像:

with sample_data as (select 'dep1' department, 'pos1' position, 'employee1' employee, to_date('19/02/2015 16:00', 'dd/mm/yyyy hh24:mi:ss') last_update from dual union all
                     select 'dep1' department, 'pos2' position, 'employee1' employee, to_date('19/02/2015 08:00', 'dd/mm/yyyy hh24:mi:ss') last_update from dual union all
                     select 'dep1' department, 'pos3' position, 'employee1' employee, to_date('19/02/2015 11:00', 'dd/mm/yyyy hh24:mi:ss') last_update from dual union all
                     select 'dep2' department, 'pos4' position, 'employee2' employee, to_date('19/02/2015 13:00', 'dd/mm/yyyy hh24:mi:ss') last_update from dual union all
                     select 'dep2' department, 'pos5' position, 'employee2' employee, to_date('19/02/2015 09:00', 'dd/mm/yyyy hh24:mi:ss') last_update from dual union all
                     select 'dep2' department, 'pos6' position, 'employee3' employee, to_date('19/02/2015 07:00', 'dd/mm/yyyy hh24:mi:ss') last_update from dual)
select department, position, employee, last_update
from   (select sd.*,
               row_number() over (partition by department, employee order by last_update desc) rn
        from   sample_data sd)
where  rn = 1;

DEPARTMENT POSITION EMPLOYEE  LAST_UPDATE          
---------- -------- --------- ---------------------
dep1       pos1     employee1 19/02/2015 16:00:00  
dep2       pos4     employee2 19/02/2015 13:00:00  
dep2       pos6     employee3 19/02/2015 07:00:00  

答案 1 :(得分:1)

您可以按子查询中的单独部门和员工列进行分组,并且您不希望在其中包含该职位;然后在两个列的外部查询连接中:

SELECT t.department, t.position, t.employee,
  to_char(r.MaxTime, 'HH24:MI') as MaxTime
FROM (SELECT department, employee, MAX(last_update) as MaxTime
      FROM employeetable
      GROUP BY department, employee) r
INNER JOIN employeetable t ON t.department = r.department
  AND t.employee = r.employee
  AND t.last_update = r.MaxTime;

DEPARTMENT POSITION EMPLOYEE   MAXTIME
---------- -------- ---------- -------
dep1       pos1     employee1  16:00   
dep2       pos4     employee2  13:00   
dep2       pos6     employee3  07:00   

您还可以在子查询中使用分析排名函数来避免自联接:

SELECT department, position, employee,
  to_char(last_update, 'HH24:MI') as maxtime
FROM (
  SELECT department, position, employee, last_update,
    rank() over (partition by department, employee
      order by last_update desc) as rnk
  FROM employeetable
)
WHERE rnk = 1;

或使用max keep first dense_rank

SELECT department,
  max(position) keep (dense_rank first order by last_update desc) as position,
  employee,
  to_char(max(last_update)
    keep (dense_rank first order by last_update desc), 'HH24:MI') as maxtime
FROM employeetable
GROUP BY department, employee;

我假设您的last_update列确实是一个约会,而您只是为了简洁而展示时间;否则你需要转换价值,并且你无法在不同的日子里对时间进行排名......

SQL Fiddle采用这三种方法。

答案 2 :(得分:0)

保持简单:

SELECT department, position, employee, last_update 
  FROM 
  (
   SELECT department, position, employee, last_update
   , ROW_NUMBER() OVER (PARTITION BY employee, department ORDER BY department, employee, last_update DESC) rseq
     FROM
  (
   select 'dep1' department, 'pos1' position, 'employee1' employee, to_char(to_date('19/02/2015 16:00', 'dd/mm/yyyy hh24:mi:ss'), 'mm-dd-yyyy hh24:mi:ss') last_update from dual union all
   select 'dep1' department, 'pos2' position, 'employee1' employee, to_char(to_date('19/02/2015 08:00', 'dd/mm/yyyy hh24:mi:ss'), 'mm-dd-yyyy hh24:mi:ss') last_update from dual union all
   select 'dep1' department, 'pos3' position, 'employee1' employee, to_char(to_date('19/02/2015 11:00', 'dd/mm/yyyy hh24:mi:ss'), 'mm-dd-yyyy hh24:mi:ss') last_update from dual union all
   select 'dep2' department, 'pos4' position, 'employee2' employee, to_char(to_date('19/02/2015 13:00', 'dd/mm/yyyy hh24:mi:ss'), 'mm-dd-yyyy hh24:mi:ss') last_update from dual union all
   select 'dep2' department, 'pos5' position, 'employee2' employee, to_char(to_date('19/02/2015 09:00', 'dd/mm/yyyy hh24:mi:ss'), 'mm-dd-yyyy hh24:mi:ss') last_update from dual union all
   select 'dep2' department, 'pos6' position, 'employee3' employee, to_char(to_date('19/02/2015 07:00', 'dd/mm/yyyy hh24:mi:ss'), 'mm-dd-yyyy hh24:mi:ss') last_update from dual
   )
 )
WHERE rseq = 1
/

dep1    pos1    employee1   02-19-2015 16:00:00
dep2    pos4    employee2   02-19-2015 13:00:00
dep2    pos6    employee3   02-19-2015 07:00:00

答案 3 :(得分:0)

怎么样:

SELECT t.department, t.position, t.employee , t.last_update
From employeetable t
Where not exists (
  SELECT 'x'
  From employeetable t2
  Where t2.employee=t.employee
    and t2.last_update > t.last_update
  )