我有一个分层的公司结构,其中每个公司都有一个可选的公司部门。子公司如果没有自己的子公司,则继承其父公司的部门,但是如果子公司不继承子公司,则子公司的部门优先于父公司。
我需要生成按部门分组的账单金额之和。没有部门的公司将被忽略。
“公司”表中的ParentCompanyID列是其自身的外键。父/子级别可以不限数量。
公司表
CompanyID ParentCompanyID
1 null
2 1
3 2
4 null
5 4
6 null
7 6
8 7
CompanySector表
CompanyID Sector
1 Distribution
4 Distribution
5 Manufacturing
8 Manufacturing
时间表表
CompanyID BillAmount
1 100
1 200
2 100
3 50
4 25
5 75
6 75
7 115
8 115
我希望在这里看到的结果是:
Sector BillAmount
Distribution 475
Manufacturing 190
以下是我当前的操作方式。它效率极低,不适用于无限数量的层次结构级别。
WITH Company AS
( SELECT 1 CompanyID, NULL ParentCompanyID FROM dual
UNION
SELECT 2, 1 FROM dual
UNION
SELECT 3, 2 FROM dual
UNION
SELECT 4, NULL FROM dual
UNION
SELECT 5, 4 FROM dual
UNION
SELECT 6, NULL FROM dual
UNION
SELECT 7, 6 FROM dual
UNION
SELECT 8, 7 FROM dual
),
CompanySector AS
( SELECT 1 CompanyID, 'Distribution' Sector FROM dual
UNION
SELECT 4 , 'Distribution' FROM dual
UNION
SELECT 5 , 'Manufacturing' FROM dual
UNION
SELECT 8 , 'Manufacturing' FROM dual
),
Timesheets AS
( SELECT 1 CompanyID, 100 BillAmount FROM dual
UNION
SELECT 1 CompanyID, 200 BillAmount FROM dual
UNION
SELECT 2 CompanyID, 100 BillAmount FROM dual
UNION
SELECT 3 CompanyID, 50 BillAmount FROM dual
UNION
SELECT 4 CompanyID, 25 BillAmount FROM dual
UNION
SELECT 5 CompanyID, 75 BillAmount FROM dual
UNION
SELECT 6 CompanyID, 75 BillAmount FROM dual
UNION
SELECT 7 CompanyID, 115 BillAmount FROM dual
UNION
SELECT 8 CompanyID, 115 BillAmount FROM dual
),
--Dummy tables above
--My current way of doing it below
companies AS
(SELECT c.*,
cs.sector
FROM company c
LEFT OUTER JOIN CompanySector cs
ON c.companyID = cs.companyID
),
sectors AS
(SELECT levelOne.companyID,
NVL(levelOne.sector, NVL(levelTwo.sector, NVL(levelThree.sector, NULL))) sector
FROM companies levelOne
LEFT OUTER JOIN companies levelTwo
ON levelOne.parentcompanyid = levelTwo.companyID
LEFT OUTER JOIN companies levelThree
ON levelTwo.parentcompanyid = levelThree.companyID
WHERE NVL(levelOne.sector, NVL(levelTwo.sector, NVL(levelThree.sector, NULL))) IS NOT NULL
)
SELECT s.sector,
SUM(t.billamount)
FROM sectors s
INNER JOIN timesheets t
ON s.companyID = t.companyID
GROUP BY sector;
什么是更清洁,更有效的方法?
答案 0 :(得分:1)
我相信这会做到的。使用分层查询语法,在需要的地方从父记录中填充扇区。
WITH
base_sectors AS (
SELECT * FROM company LEFT OUTER JOIN companySector USING (companyID)
)
, final_sectors AS (
SELECT companyID, NVL( sector, PRIOR sector ) AS sector
FROM base_sectors
START WITH parentCompanyID IS NULL
CONNECT BY parentCompanyID = PRIOR companyID
)
SELECT s.sector,
SUM(t.billamount)
FROM final_sectors s
INNER JOIN timesheets t
ON s.companyID = t.companyID
GROUP BY sector;