Reputation: 143
I have a table showing employees with their departments and their positions and the last_update of their positions. My objective is to list the latest position of each one in each departement (MAX last_update by department) for each employee. But the problem is that i can't concatenate two columns and group them after through this concatenation.
So for example the table is
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
The desired result should be:
Departement Position employee last_update
dep1 pos1 employee1 16:00
dep2 pos4 employee2 13:00
dep2 pos6 employee3 07:00
i have to concatenate the employee and his department and group them by their department and the name of the employee to get the result. But i can't have a concat into a group by like this with 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
Thanks a lot
Upvotes: 0
Views: 380
Reputation: 5782
Keeping it simple:
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
Upvotes: 0
Reputation: 191265
You can group by the separate department and employee columns in the subquery, and you don't want to include the position in that either; then in the outer query join on both columns:
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
You could also use an analytic ranking function in the subquery to avoid a self join:
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;
Or using max with 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;
I'm assuming your last_update
column is really a date, and you're only showing the time for brevity; otherwise you'd need to convert the value, and you'd have no way to rank times on different days...
SQL Fiddle with all three approaches.
Upvotes: 1
Reputation: 577
How about:
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
)
Upvotes: 0
Reputation: 23578
Why are you trying to group by the concatenation of two columns and not just the two columns themselves? Also, what is the datatype of the last_update
column? I sincerely hope that it's either a DATE
or a TIMESTAMP
. Having said that, what is it you're trying to do - find the latest row for each department and employee? If so, then something like:
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
Upvotes: 1