2015-02-19 2 views
0

У меня есть таблица, показывающая сотрудников с их отделами и их положениями и последней точкой их позиций. Моя цель - перечислить последнюю позицию каждого из них в каждом отделении (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 

я должен сцепить работника и его отдел и сгруппировать их по их отдела и имя из чтобы получить результат. Но я не могу иметь CONCAT в группе, как это с оракулом:

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 

Спасибо большое

+0

Можете ли вы изменить что вниз на один вопрос? –

ответ

1

Почему вы пытаетесь группе конкатенации двух столбцов, а не только две колонки самих себя? Кроме того, каков тип данных столбца last_update? Я искренне надеюсь, что это либо DATE, либо TIMESTAMP. Сказав это, что вы пытаетесь сделать - найдите последнюю строку для каждого отдела и сотрудника? Если да, то что-то вроде:

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 
+0

Вы изменили свое сообщение (и потеряли красивое форматирование, которое сделал Алекс, пожалуйста, отредактируйте его, чтобы отметить блоки кода), но, надеюсь, пример, который я предоставил, будет достаточным, чтобы помочь вам разобраться в том, что вам нужно сделать , – Boneist

+0

Благодарим вас за ответ. Действительно, last_update является значением datetime. Проблема в том, что сотрудник находится в другой таблице, чем отдел, где есть промежуточная таблица для перемещения таблицы, содержащей сотрудника, в его отдел. Я постараюсь привести его в свои условия. – user3082877

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; 

Или используя макс с 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 со всеми тремя подходами.

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 
+0

Это не дает вам позиции. –

+0

Правда, спасибо. Я переписал ... – Art

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 
) 
Смежные вопросы