想象一下,我们有表emps,包含父子关系:
manager employee
------- ----------
NULL Johnson
Johnson Ketler
Ketler Braun
Ketler Cooper
和表合同,包含员工讨价还价的历史:
date_of_contract employee amount_of_contract
---------------- ---------- ------------------
25.03.2015 Ketler 4
25.03.2015 Braun 3
25.03.2015 Cooper 2
25.03.2015 Johnson 9
26.03.2015 Ketler 1
26.03.2015 Braun 4
26.03.2015 Cooper 3
26.03.2015 Johnson 6
27.03.2015 Ketler 6
27.03.2015 Braun 2
27.03.2015 Cooper 5
27.03.2015 Johnson 7
我们进行查询以查看2015年3月25日的等级合约总和:
with t0 as (
select e.manager, e.employee, c.date_of_contract, c.amount_of_contract
from emps e inner join
contracts c on c.employee=e.employee where date_of_contract = to_date('25.03.15')
), t1 as (
select t.*, (
select sum(amount_of_contract) from t0 p
connect by prior employee = manager
start with p.employee = t.employee
) tot, level lvl
from t0 t
connect by prior t.employee = t.manager
start with t.manager is null
)
select
lpad(' ',2*(lvl-1)) || employee employee,
tot tot_25_03_15
from t1 t
此查询产生以下结果:
EMPLOYEE TOT_25_03_15
--------- ------------
Johnson 18
Ketler 9
Braun 3
Cooper 2
目标是在单个查询中获得合同表中所有可能日期的类似结果,在给定示例中将遵循以下结果:
EMPLOYEE TOT_25_03_15 TOT_26_03_15 TOT_27_03_15
-------------- ------------- ------------- -------------
Johnson 18 14 20
Ketler 9 8 13
Braun 3 4 2
Cooper 2 3 5
P.S。 以下是创建emps和合同的代码:
create table emps (manager varchar2(50), employee varchar2(50));
insert into emps (manager, employee) values (NULL,'Johnson');
insert into emps (manager, employee) values ('Johnson','Ketler');
insert into emps (manager, employee) values ('Ketler','Braun');
insert into emps (manager, employee) values ('Ketler','Cooper');
create table contracts (date_of_contract date, employee varchar2(50), amount_of_contract number(12,0));
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('25.03.2015'),'Ketler',4);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('25.03.2015'),'Braun',3);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('25.03.2015'),'Cooper',2);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('25.03.2015'),'Johnson',9);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('26.03.2015'),'Ketler',1);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('26.03.2015'),'Braun',4);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('26.03.2015'),'Cooper',3);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('26.03.2015'),'Johnson',6);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('27.03.2015'),'Ketler',6);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('27.03.2015'),'Braun',2);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('27.03.2015'),'Cooper',5);
insert into contracts (date_of_contract, employee, amount_of_contract) values (to_date('27.03.2015'),'Johnson',7);
答案 0 :(得分:2)
您可以使用Pivot首先旋转值,然后对各个日期执行求和
WITH pivoted AS
(
SELECT employee,
"'25-MAR-15'" s25_03_15,
"'26-MAR-15'" s26_03_15,
"'27-MAR-15'" s27_03_15
FROM contracts PIVOT ( Sum( amount_of_contract) FOR date_of_contract IN ('25-MAR-15',
'26-MAR-15',
'27-MAR-15')) ) , t0 AS
(
SELECT e.manager,
e.employee,
c.s25_03_15,
c.s26_03_15,
c.s27_03_15
FROM pivoted c
INNER JOIN emps e
ON c.employee=e.employee ) , t1 AS
(
SELECT t.*,
(
SELECT sum(s25_03_15)
FROM t0 p connect BY prior employee = manager start WITH p.employee = t.employee ) tot_25_03_15,
(
SELECT sum(s26_03_15)
FROM t0 p connect BY prior employee = manager start WITH p.employee = t.employee ) tot_26_03_15,
(
SELECT sum(s27_03_15)
FROM t0 p connect BY prior employee = manager start WITH p.employee = t.employee ) tot_27_03_15,
level lvl
FROM t0 t connect BY prior t.employee = t.manager start WITH t.manager IS NULL)
SELECT lpad(' ',2*(lvl-1))
|| employee employee,
tot_25_03_15 ,
tot_26_03_15 ,
tot_27_03_15
FROM t1 t
对于对节点进行求和的内联SQL,我并不感到兴奋所以这里是一个使用SYS_CONNECT_BY_PATH和LIKE上的自联接的替代方法
WITH pivoted AS
(
SELECT employee,
"'25-MAR-15'" s25_03_15,
"'26-MAR-15'" s26_03_15,
"'27-MAR-15'" s27_03_15
FROM contracts PIVOT ( Sum( amount_of_contract) FOR date_of_contract IN ('25-MAR-15',
'26-MAR-15',
'27-MAR-15')) ) , t0 AS
(
SELECT e.manager,
e.employee,
c.s25_03_15,
c.s26_03_15,
c.s27_03_15
FROM pivoted c
INNER JOIN emps e
ON c.employee=e.employee ) , t1 AS
(
SELECT t.*,
sys_connect_by_path(employee, '/') path,
level lvl
FROM t0 t connect BY prior t.employee = t.manager start WITH t.manager IS NULL)
SELECT lpad(' ',2*(b.lvl-1))
|| b.employee employee,
sum(a.s25_03_15) tot_25_03_15,
sum(a.s26_03_15) tot_26_03_15,
sum(a.s27_03_15) tot_26_03_15
FROM t1 a
INNER JOIN t1 b
ON a.path LIKE b.path
|| '%'
GROUP BY lpad(' ',2*(b.lvl-1))
|| b.employee