在Oracle中合并同一员工的不同记录

时间:2019-01-15 11:38:34

标签: sql oracle

我需要以这样一种方式显示数据,即对于一个雇员来说,存在多个费用,即当期费用或其他费用,并且我需要合并那些当前同时具有额外费用和当前费用的雇员的列,我写了一个查询来获取记录。

       SELECT 
DISTINCT ost.EMP_ID,
E.name emp_name,
E.EMP_CODE emloyee_code,
L.NAME Official_loc,
DEP.name DEPARTMENT_NAME,
LISTAGG(DEP.name,'|') WITHIN GROUP (ORDER BY DEP.name )DEPARTMENT_NAME,
D.NAME DESIGNATION_NAME, 
ost.UPDATE_BY,
ost.UPDATE_DATE,
ost.UPDATE_BY_NAME,
LISTAGG(ost.CHARGE,'|')WITHIN GROUP (ORDER BY ost.CHARGE) AS CHARGE,
--ost.CHARGE,
ost.OFFICIAL_LOCATION_ID,
ost.STATUS 
FROM ORG_STRUCTURE_TAGGING ost
JOIN EMPLOYEE E 
ON E.EMP_ID=ost.EMP_ID
LEFT JOIN DESIGNATION D
ON D.DESIGNATION_ID=ost.DESIGNATION_ID
LEFT JOIN DEPARTMENT DEP
ON DEP.DEPARTMENT_ID=ost.DEPARTMENT_ID
LEFT JOIN LOCATION L
ON L.LOCATION_ID=ost.OFFICIAL_LOCATION_ID
WHERE ost.STATUS=1 
group by ost.EMP_ID, E.name, E.EMP_CODE, L.NAME, DEP.name, 
ost.DESIGNATION_ID, D.NAME, ost.UPDATE_BY, ost.UPDATE_DATE, ost.UPDATE_BY_NAME, 
ost.OFFICIAL_LOCATION_ID, ost.STATUS 

输出:

614 Abraham Oommen  1541032 Corporate Office    National Events Computer Operator   11-JAN-19   Super Administrator Additional Charge
633 Mukesh R Sharma 1051009 Corporate Office    Content Management (National Events)    Executive Director  14-JAN-19   Super Administrator Current Charge
686 Nousara Khadka  1051019 Corporate Office    Content Management (National Events)    Executive Engineer  11-JAN-19   Super Administrator Current Charge
688 Prem Lal Namdeo 1051029 Corporate Office    Pre & Post Allotment    Computer Operator   11-JAN-19   Super Administrator Current Charge
364 Kumari Sapna    1031036 Corporate Office    Events & Roadshows (International Events)   Manager 15-JAN-19   Super Administrator Additional Charge
364 Kumari Sapna    1031036 Corporate Office    Events & Roadshows (International Events)   Computer Operator   14-JAN-19   Super Administrator Current Charge
614 Abraham Oommen  1541032 Corporate Office    Content Management (International Events)   Assistant Grade 2   11-JAN-19   Super Administrator Current Charge
469 Pooja Bhimte    1071025 Corporate Office    Content Management (International Events)   Chief General Manager   14-JAN-19   Super Administrator Current Charge
242 Vijay Sugandhi  1023014 Corporate Office    Allotment   Executive Engineer  15-JAN-19   Super Administrator Current Charge
686 Nousara Khadka  1051019 Corporate Office    Procurement Senior Accountant   11-JAN-19   Super Administrator Additional Charge

根据单个雇员的输出,我们有两个名称和费用,我想将其合并为单列,并保持其值的逗号分隔。

例如:EMP ID 614有两个记录

EMP ID, EMP_NAME,    EMP_CODE,     LOCATION,         DESIGNATION,  ASSIGNED SECTION
    614 Abraham Oommen  1541032 Corporate Office    Content Management (International Events),National Events   "Assistant Grade 2-->current Charge,Computer Operator--> Additional Charge"

DESIGNATION should be output as "Content Management (International Events),National Events Computer Operator"

ASSIGNED_SECTION should be output as "Assistant Grade 2-current Charge,Computer Operator- Additional Charge"

截至目前,这些值属于同一员工,但位于不同的列中,我想将其合并,请为我提出解决方案。

TABLE STRUCTURE:

ORG_STRUCTURE_TAGGING_ID    NUMBER  Yes     1   
EMP_ID  NUMBER  Yes     2   
DEPARTMENT_ID   VARCHAR2(2 BYTE)    Yes     3   
DESIGNATION_ID  VARCHAR2(50 BYTE)   Yes     4   
UPDATE_BY   NUMBER  Yes     5   
UPDATE_DATE DATE    Yes     6   
UPDATE_BY_NAME  VARCHAR2(100 BYTE)  Yes     7   
CHARGE  VARCHAR2(100 BYTE)  Yes     8   
OFFICIAL_LOCATION_ID    VARCHAR2(2 BYTE)    Yes     9   
STATUS  NUMBER  Yes     10  
ENTRY_BY    NUMBER  Yes     11  
ENTRY_DATE  DATE    Yes     12  
APPROVED_BY NUMBER  Yes     13  
APPROVED_DATE   DATE    Yes     14

2 个答案:

答案 0 :(得分:2)

这是查询的简化版本,其结果应与您的预期输出匹配。

如评论中所述,每个未聚合的列必须出现在GROUP BY子句中,而聚合的列不应出现在GROUP BY中。在您显示的查询中,DEP.name列与LISTAGG聚合在一起,但也出现在GROUP BY中:因此,实际上没有任何聚合。

我删除了所有未出现在预期结果中的SELECT字段(例如CHARGE),并使用LISTAGG进行汇总:

SELECT DISTINCT 
    ost.EMP_ID,
    E.name emp_name,
    E.EMP_CODE emloyee_code,
    L.NAME Official_loc,
    LISTAGG(DEP.name,',') WITHIN GROUP (ORDER BY DEP.name) DESIGNATION,
    LISTAGG(D.name, ',') WITHIN GROUP (ORDER BY D.name) ASSIGNED_SECTION
FROM 
    ORG_STRUCTURE_TAGGING ost
    JOIN EMPLOYEE E ON E.EMP_ID=ost.EMP_ID
    LEFT JOIN DESIGNATION D ON D.DESIGNATION_ID=ost.DESIGNATION_ID
    LEFT JOIN DEPARTMENT DEP ON DEP.DEPARTMENT_ID=ost.DEPARTMENT_ID
    LEFT JOIN LOCATION L ON L.LOCATION_ID=ost.OFFICIAL_LOCATION_ID
WHERE 
    ost.STATUS=1 
GROUP BY 
    ost.EMP_ID,
    E.name,
    E.EMP_CODE,
    L.NAME

答案 1 :(得分:2)

基于您所说的正在寻找的更复杂的输出,您似乎想要这样的东西:

select
  ost.emp_id,
  e.name emp_name,
  e.emp_code emloyee_code,
  l.name official_loc,
  listagg(dep.name, ',')
    within group (order by dep.name) as departments,
  listagg(d.name || '-' || ost.charge, ',')
    within group (order by ost.charge desc, d.name) as designations,
  ost.update_by,
  ost.update_date,
  ost.update_by_name,
  ost.status 
from org_structure_tagging ost
join employee e on e.emp_id=ost.emp_id
left join designation d on d.designation_id=ost.designation_id
left join department dep on dep.department_id=ost.department_id
left join location l on l.location_id=ost.official_location_id
where ost.status=1 
group by 
  ost.emp_id, 
  e.name, 
  e.emp_code, 
  l.name, 
  ost.update_by, 
  ost.update_date, 
  ost.update_by_name, 
  ost.status;

我可能以错误的顺序排列了列名,因为不清楚输出中的哪个。但这只是部门名称的简单汇总,而串联的名称和费用值的汇总则稍微复杂些。

或者为防止重复,请在汇总之前使用适用distinct的子查询:

select
  emp_id,
  emp_name,
  employee_code,
  official_loc,
  listagg(department, ',')
    within group (order by department) as departments,
  listagg(designation || '-' || charge, ',')
    within group (order by charge desc, designation) as designations,
  update_by,
  update_date,
  update_by_name,
  status 
from(
  select distinct
    ost.emp_id,
    e.name emp_name,
    e.emp_code employee_code,
    l.name official_loc,
    dep.name as department,
    d.name as designation,
    ost.charge,
    ost.update_by,
    ost.update_date,
    ost.update_by_name,
    ost.status 
  from org_structure_tagging ost
  join employee e on e.emp_id=ost.emp_id
  left join designation d on d.designation_id=ost.designation_id
  left join department dep on dep.department_id=ost.department_id
  left join location l on l.location_id=ost.official_location_id
  where ost.status=1
)
group by 
  emp_id, 
  emp_name, 
  employee_code, 
  official_loc,
  update_by, 
  update_date, 
  update_by_name, 
  status;