获取分层 table 中子项列表的根元素
Get root elements for list of children in hierarchical table
我有以下 2 个表,第一个包含分层数据:
公司:
COMPANY_ID PARENT_COMPANY_ID
---------- -----------------
1 NULL
2 1
3 2
4 3
5 NULL
6 5
用户:
USER_ID COMPANY_ID
------- ----------
1 1
2 4
3 5
4 6
我想进行一个查询,在其根公司 ID 旁边输出用户 ID。我尝试使用以下 Common Table Expression (CTE) 查询,但它无法输出直接在根公司下的用户:
查询:
WITH ROOT (COMPANY_ID, ROOT_ID) AS (
SELECT
CHILD.COMPANY_ID,
PARENT.COMPANY_ID
FROM COMPANIES CHILD
INNER JOIN COMPANIES PARENT
ON CHILD.PARENT_COMPANY_ID = PARENT.COMPANY_ID
WHERE
PARENT.PARENT_COMPANY_ID IS NULL
UNION ALL
SELECT
C.COMPANY_ID,
ROOT.ROOT_ID
FROM ROOT
INNER JOIN COMPANIES C
ON ROOT.COMPANY_ID = C.PARENT_COMPANY_ID
)
SELECT
U.USER_ID,
R.ROOT_ID
FROM USERS U
INNER JOIN ROOT R
ON U.COMPANY_ID = R.COMPANY_ID;
实际输出:
USER_ID ROOT_COMPANY_ID
------- ---------------
4 5
2 1
预期输出:
USER_ID ROOT_COMPANY_ID
------- ---------------
1 1
2 1
3 5
4 5
所以我的查询缺少用户 ID 为 1 和 2 的用户及其各自的根公司 1 和 5。
我用我的例子创建了这个 sqlfiddle:
http://sqlfiddle.com/#!4/36d33a/1
我在这里错过了什么?
我正在使用 Oracle 11,但使用 H2 进行单元测试。所以我的查询需要是 CTE 查询而不是 Oracle 连接查询,因为 H2 只理解前者。
对于根公司,您需要 select COMPANY_ID
作为 COMPANY_ID
和 ROOT_ID
:
WITH ROOT(COMPANY_ID, ROOT_ID) AS (
SELECT COMPANY_ID, COMPANY_ID FROM COMPANIES WHERE PARENT_COMPANY_ID IS NULL
UNION ALL
SELECT C.COMPANY_ID, ROOT.ROOT_ID FROM COMPANIES C JOIN ROOT
ON C.PARENT_COMPANY_ID = ROOT.COMPANY_ID
) SELECT USER_ID, ROOT_ID FROM USERS JOIN ROOT
ON USERS.COMPANY_ID = ROOT.COMPANY_ID;
您可以使用 Oracle 的经典分层查询包括 CONNECT_BY_ROOT
和 ROW_NUMBER()
分析函数来过滤掉第一个查询(子查询)中的根公司 companies
table, 然后加入 users
table :
WITH company AS
(
SELECT c.company_id,
CONNECT_BY_ROOT NVL(c.parent_company_id,c.company_id) AS root_company_id,
ROW_NUMBER() OVER (PARTITION BY c.company_id ORDER BY level DESC) AS rn
FROM companies c
CONNECT BY PRIOR c.company_id = c.parent_company_id
)
SELECT u.user_id, c.root_company_id
FROM company c
JOIN users u
ON u.company_id = c.company_id
WHERE rn = 1
我有以下 2 个表,第一个包含分层数据:
公司:
COMPANY_ID PARENT_COMPANY_ID
---------- -----------------
1 NULL
2 1
3 2
4 3
5 NULL
6 5
用户:
USER_ID COMPANY_ID
------- ----------
1 1
2 4
3 5
4 6
我想进行一个查询,在其根公司 ID 旁边输出用户 ID。我尝试使用以下 Common Table Expression (CTE) 查询,但它无法输出直接在根公司下的用户:
查询:
WITH ROOT (COMPANY_ID, ROOT_ID) AS (
SELECT
CHILD.COMPANY_ID,
PARENT.COMPANY_ID
FROM COMPANIES CHILD
INNER JOIN COMPANIES PARENT
ON CHILD.PARENT_COMPANY_ID = PARENT.COMPANY_ID
WHERE
PARENT.PARENT_COMPANY_ID IS NULL
UNION ALL
SELECT
C.COMPANY_ID,
ROOT.ROOT_ID
FROM ROOT
INNER JOIN COMPANIES C
ON ROOT.COMPANY_ID = C.PARENT_COMPANY_ID
)
SELECT
U.USER_ID,
R.ROOT_ID
FROM USERS U
INNER JOIN ROOT R
ON U.COMPANY_ID = R.COMPANY_ID;
实际输出:
USER_ID ROOT_COMPANY_ID
------- ---------------
4 5
2 1
预期输出:
USER_ID ROOT_COMPANY_ID
------- ---------------
1 1
2 1
3 5
4 5
所以我的查询缺少用户 ID 为 1 和 2 的用户及其各自的根公司 1 和 5。
我用我的例子创建了这个 sqlfiddle: http://sqlfiddle.com/#!4/36d33a/1
我在这里错过了什么?
我正在使用 Oracle 11,但使用 H2 进行单元测试。所以我的查询需要是 CTE 查询而不是 Oracle 连接查询,因为 H2 只理解前者。
对于根公司,您需要 select COMPANY_ID
作为 COMPANY_ID
和 ROOT_ID
:
WITH ROOT(COMPANY_ID, ROOT_ID) AS (
SELECT COMPANY_ID, COMPANY_ID FROM COMPANIES WHERE PARENT_COMPANY_ID IS NULL
UNION ALL
SELECT C.COMPANY_ID, ROOT.ROOT_ID FROM COMPANIES C JOIN ROOT
ON C.PARENT_COMPANY_ID = ROOT.COMPANY_ID
) SELECT USER_ID, ROOT_ID FROM USERS JOIN ROOT
ON USERS.COMPANY_ID = ROOT.COMPANY_ID;
您可以使用 Oracle 的经典分层查询包括 CONNECT_BY_ROOT
和 ROW_NUMBER()
分析函数来过滤掉第一个查询(子查询)中的根公司 companies
table, 然后加入 users
table :
WITH company AS
(
SELECT c.company_id,
CONNECT_BY_ROOT NVL(c.parent_company_id,c.company_id) AS root_company_id,
ROW_NUMBER() OVER (PARTITION BY c.company_id ORDER BY level DESC) AS rn
FROM companies c
CONNECT BY PRIOR c.company_id = c.parent_company_id
)
SELECT u.user_id, c.root_company_id
FROM company c
JOIN users u
ON u.company_id = c.company_id
WHERE rn = 1