Oracle 将两行合并为具有更多列的单行
Oracle merge two rows as single row with more columns
我有两个表 Employee,Employeerows。我必须提取具有角色 2 或 3 的员工记录。
我有以下查询。
SELECT
E.ID,
E.NAME,
ER.PHONE,
ER.ADDRESS,
ER.ROLE
FROM
EMPLOYEE E LEFT JOIN EMPLOYEEROWS ER ON E.ID = ER.ID WHERE ER.ROLE_ID IN (2,3)
每个员工 returns 1 或 2 条记录
ID NAME PHONE ADDRESS ROLE
1 ABC 9898989 ABC NJ 2
1 ABC 7878787 ABC XJ 3
2 DEF 7898765 DEF NJ 2
但是如果该员工有 2 条记录,我必须将 phone 编号和地址作为单独列的该员工的两条记录合并为一条。 我的结果应该是这样的。
ID NAME PHONE ALT_PHONE ADDRESS ALT_ADDESS
1 ABC 9898989 7878787 ABC NJ ABC XJ
2 DEF 7898765 DEF NJ
请帮我解决这个问题。
您可以使用条件聚合进行透视:
select e.id, e.name,
max(case when er.role_id = 2 then er.phone end) as phone,
max(case when er.role_id = 3 then er.phone end) as alt_phone,
max(case when er.role_id = 2 then er.address end) as address,
max(case when er.role_id = 3 then er.address end) as alt_address
from employee e
left join employeerows er on e.id = er.id where er.role_id in (2,3)
group by e.id, e.name
您可以使用条件聚合。但是您的查询 没有执行 LEFT OUTER JOIN
但它是 INNER JOIN
因为您在 WHERE
子句中使用了 er.role_id in (2,3)
。
使用以下聚合技术获取所需结果:
SELECT
E.ID,
E.NAME,
MIN(ER.PHONE),
CASE WHEN MIN(ER.PHONE) <> MAX(ER.PHONE) THEN MAX(ER.PHONE) END AS ALT_PHONE,
MIN(ER.ADDRESS),
CASE WHEN MIN(ER.ADDRESS) <> MAX(ER.ADDRESS) THEN MAX(ER.ADDRESS) END AS ALT_ADDRESS
FROM EMPLOYEE E
LEFT JOIN EMPLOYEEROWS ER ON E.ID = ER.ID
AND ER.ROLE_ID IN (2,3) -- added it in the join condition
GROUP BY E.ID, E.NAME;
您可以使用条件聚合。但是 left join
似乎是多余的。如果您想要没有行的“员工”,您只想使用 left join
。
根据您的数据,“2”对应主地址,“3”对应备用地址:
select e.id, e.name,
max(case when er.role_id = 2 then er.phone end) as phone,
max(case when er.role_id = 3 then er.phone end) as alt_phone,
max(case when er.role_id = 2 then er.address end) as address,
max(case when er.role_id = 3 then er.address end) as alt_address
from employee e join
employeerows er
on e.id = er.id
where er.role_id in (2, 3)
group by e.id, e.name;
但是,如果可能缺少“2”,那么您可以将其表述为:
select e.id, e.name,
max(case when seqnum = 2 then er.phone end) as phone,
max(case when seqnum = 3 then er.phone end) as alt_phone,
max(case when seqnum = 2 then er.address end) as address,
max(case when seqnum = 3 then er.address end) as alt_address
from employee e join
(select er.*,
row_number() over (partition by er.id order by er.role_id) as seqnum
from employeerows er
where er.role_id in (2, 3)
) er
on e.id = er.id
group by e.id, e.name;
我有两个表 Employee,Employeerows。我必须提取具有角色 2 或 3 的员工记录。 我有以下查询。
SELECT
E.ID,
E.NAME,
ER.PHONE,
ER.ADDRESS,
ER.ROLE
FROM
EMPLOYEE E LEFT JOIN EMPLOYEEROWS ER ON E.ID = ER.ID WHERE ER.ROLE_ID IN (2,3)
每个员工 returns 1 或 2 条记录
ID NAME PHONE ADDRESS ROLE
1 ABC 9898989 ABC NJ 2
1 ABC 7878787 ABC XJ 3
2 DEF 7898765 DEF NJ 2
但是如果该员工有 2 条记录,我必须将 phone 编号和地址作为单独列的该员工的两条记录合并为一条。 我的结果应该是这样的。
ID NAME PHONE ALT_PHONE ADDRESS ALT_ADDESS
1 ABC 9898989 7878787 ABC NJ ABC XJ
2 DEF 7898765 DEF NJ
请帮我解决这个问题。
您可以使用条件聚合进行透视:
select e.id, e.name,
max(case when er.role_id = 2 then er.phone end) as phone,
max(case when er.role_id = 3 then er.phone end) as alt_phone,
max(case when er.role_id = 2 then er.address end) as address,
max(case when er.role_id = 3 then er.address end) as alt_address
from employee e
left join employeerows er on e.id = er.id where er.role_id in (2,3)
group by e.id, e.name
您可以使用条件聚合。但是您的查询 没有执行 LEFT OUTER JOIN
但它是 INNER JOIN
因为您在 WHERE
子句中使用了 er.role_id in (2,3)
。
使用以下聚合技术获取所需结果:
SELECT
E.ID,
E.NAME,
MIN(ER.PHONE),
CASE WHEN MIN(ER.PHONE) <> MAX(ER.PHONE) THEN MAX(ER.PHONE) END AS ALT_PHONE,
MIN(ER.ADDRESS),
CASE WHEN MIN(ER.ADDRESS) <> MAX(ER.ADDRESS) THEN MAX(ER.ADDRESS) END AS ALT_ADDRESS
FROM EMPLOYEE E
LEFT JOIN EMPLOYEEROWS ER ON E.ID = ER.ID
AND ER.ROLE_ID IN (2,3) -- added it in the join condition
GROUP BY E.ID, E.NAME;
您可以使用条件聚合。但是 left join
似乎是多余的。如果您想要没有行的“员工”,您只想使用 left join
。
根据您的数据,“2”对应主地址,“3”对应备用地址:
select e.id, e.name,
max(case when er.role_id = 2 then er.phone end) as phone,
max(case when er.role_id = 3 then er.phone end) as alt_phone,
max(case when er.role_id = 2 then er.address end) as address,
max(case when er.role_id = 3 then er.address end) as alt_address
from employee e join
employeerows er
on e.id = er.id
where er.role_id in (2, 3)
group by e.id, e.name;
但是,如果可能缺少“2”,那么您可以将其表述为:
select e.id, e.name,
max(case when seqnum = 2 then er.phone end) as phone,
max(case when seqnum = 3 then er.phone end) as alt_phone,
max(case when seqnum = 2 then er.address end) as address,
max(case when seqnum = 3 then er.address end) as alt_address
from employee e join
(select er.*,
row_number() over (partition by er.id order by er.role_id) as seqnum
from employeerows er
where er.role_id in (2, 3)
) er
on e.id = er.id
group by e.id, e.name;