自连接的分层查询 Table 最多 3 次
Hierarchical Query to Self-Join Table Max 3 Times
我有一个 Oracle 数据库 table 包含以下列:
ID | PARENTID | DETAIL1
------------------------
1 | NULL | BLAH1
2 | 1 | BLAH2
3 | 2 | BLAH3
4 | 2 | BLAH4
5 | NULL | BLAH5
6 | 5 | BLAH6
7 | 6 | BLAH7
8 | 5 | BLAH8
9 | 5 | BLAH9
10 | 8 | BLAH10
我为
准备了一个自连接
SELECT PARENT.ID AS "PID",
PARENT.DETAIL1 AS "PDETAIL1",
CHILD.ID AS "CID",
CHILD.DETAIL1 AS "CDETAIL1"
FROM table1 CHILD
LEFT OUTER JOIN table1 PARENT
ON PARENT.ID = CHILD.PARENTID
WHERE PARENTID IS NOT NULL;
输出如下所示:
PID | PDETAIL1 | CID | CDETAIL1|
--------------------------------
1 | BLAH1 | 2 | BLAH2 |
2 | BLAH2 | 3 | BLAH3 |
2 | BLAH2 | 4 | BLAH4 |
5 | BLAH5 | 6 | BLAH6 |
6 | BLAH6 | 7 | BLAH7 |
5 | BLAH5 | 8 | BLAH8 |
5 | BLAH5 | 9 | BLAH9 |
8 | BLAH8 | 10 | BLAH10 |
非常简单。我想知道这个自连接是否可以作为 hierarchical/recursive 查询来完成。最大嵌套深度为 3。目标输出应如下所示:
GPID | GPDETAIL1 | PID | PDETAIL1 | CID | CDETAIL1 |
---------------------------------------------------
1 | BLAH1 | 2 | BLAH2 | 3 | BLAH3 |
1 | BLAH1 | 2 | BLAH2 | 4 | BLAH4 |
5 | BLAH5 | 6 | BLAH6 | 7 | BLAH7 |
5 | BLAH5 | 8 | BLAH8 | 10 | BLAH10 |
5 | BLAH5 | 9 | BLAH9 | NULL | NULL |
Google 对我没有帮助,有大量与分层查询相关的信息,但没有任何信息包括自连接和分层查询,大多数问题似乎(表面上)相似,但是没有什么能指导我找到我需要的东西。我是 SQL 新手,所以除非答案具体,否则我可能会漏掉它。
你只需要再 join
到 table 一次就可以得到 children。所以基本上有一个 grandparent 别名,parent 别名和 child 别名以及相应的 join
:
select
gp.id as gpid,
gp.detail as gpdetail1,
p.id as pid,
p.detail as pdetail1,
c.id as cid,
c.detail as cdetail1
from yourtable gp
left join yourtable p on gp.id = p.parentid
left join yourtable c on p.id = c.parentid
where gp.parentid is null
there is a ton of information related to hierarchical queries, but nothing including self-joins AND hierarchical queries
您不需要两者,分层查询 是 self-join。
您可以从分层查询开始,例如:
select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
prior id as pid, prior detail1 as pdetail1,
id as cid, detail1 as cdetail1,
level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid
See the docs 表示 connect_by_root 和 connect_by_isleaf 的意思。您对叶节点感兴趣,但是:
select *
from (
select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
prior id as pid, prior detail1 as pdetail1,
id as cid, detail1 as cdetail1,
level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid
)
where is_leaf = 1;
...没有得到您想要的:
GPID GPDETA PID PDETAI CID CDETAI LVL IS_LEAF
---------- ------ ---------- ------ ---------- ------ ---------- ----------
1 BLAH1 2 BLAH2 3 BLAH3 3 1
1 BLAH1 2 BLAH2 4 BLAH4 3 1
5 BLAH5 6 BLAH6 7 BLAH7 3 1
5 BLAH5 8 BLAH8 10 BLAH10 3 1
5 BLAH5 5 BLAH5 9 BLAH9 2 1
从您的示例输出中,您不希望在最后一行的 parent 列中出现 5/BLAH5,因为它们是 grandparent;您希望将 child 值提升为 parent 状态。不过,您可以稍微操纵 parent 和 child 值:
select gpid, gpdetail1,
case lvl when 2 then cid else pid end as pid,
case lvl when 2 then cdetail1 else pdetail1 end as pdetail1,
case lvl when 2 then null else cid end as cid,
case lvl when 2 then null else cdetail1 end as cdetail1
from (
select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
prior id as pid, prior detail1 as pdetail1,
id as cid, detail1 as cdetail1,
level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid
)
where is_leaf = 1;
GPID GPDETA PID PDETAI CID CDETAI
---------- ------ ---------- ------ ---------- ------
1 BLAH1 2 BLAH2 3 BLAH3
1 BLAH1 2 BLAH2 4 BLAH4
5 BLAH5 6 BLAH6 7 BLAH7
5 BLAH5 8 BLAH8 10 BLAH10
5 BLAH5 9 BLAH9
但只有三个固定级别,再次加入更容易理解...
我有一个 Oracle 数据库 table 包含以下列:
ID | PARENTID | DETAIL1
------------------------
1 | NULL | BLAH1
2 | 1 | BLAH2
3 | 2 | BLAH3
4 | 2 | BLAH4
5 | NULL | BLAH5
6 | 5 | BLAH6
7 | 6 | BLAH7
8 | 5 | BLAH8
9 | 5 | BLAH9
10 | 8 | BLAH10
我为
准备了一个自连接 SELECT PARENT.ID AS "PID",
PARENT.DETAIL1 AS "PDETAIL1",
CHILD.ID AS "CID",
CHILD.DETAIL1 AS "CDETAIL1"
FROM table1 CHILD
LEFT OUTER JOIN table1 PARENT
ON PARENT.ID = CHILD.PARENTID
WHERE PARENTID IS NOT NULL;
输出如下所示:
PID | PDETAIL1 | CID | CDETAIL1|
--------------------------------
1 | BLAH1 | 2 | BLAH2 |
2 | BLAH2 | 3 | BLAH3 |
2 | BLAH2 | 4 | BLAH4 |
5 | BLAH5 | 6 | BLAH6 |
6 | BLAH6 | 7 | BLAH7 |
5 | BLAH5 | 8 | BLAH8 |
5 | BLAH5 | 9 | BLAH9 |
8 | BLAH8 | 10 | BLAH10 |
非常简单。我想知道这个自连接是否可以作为 hierarchical/recursive 查询来完成。最大嵌套深度为 3。目标输出应如下所示:
GPID | GPDETAIL1 | PID | PDETAIL1 | CID | CDETAIL1 |
---------------------------------------------------
1 | BLAH1 | 2 | BLAH2 | 3 | BLAH3 |
1 | BLAH1 | 2 | BLAH2 | 4 | BLAH4 |
5 | BLAH5 | 6 | BLAH6 | 7 | BLAH7 |
5 | BLAH5 | 8 | BLAH8 | 10 | BLAH10 |
5 | BLAH5 | 9 | BLAH9 | NULL | NULL |
Google 对我没有帮助,有大量与分层查询相关的信息,但没有任何信息包括自连接和分层查询,大多数问题似乎(表面上)相似,但是没有什么能指导我找到我需要的东西。我是 SQL 新手,所以除非答案具体,否则我可能会漏掉它。
你只需要再 join
到 table 一次就可以得到 children。所以基本上有一个 grandparent 别名,parent 别名和 child 别名以及相应的 join
:
select
gp.id as gpid,
gp.detail as gpdetail1,
p.id as pid,
p.detail as pdetail1,
c.id as cid,
c.detail as cdetail1
from yourtable gp
left join yourtable p on gp.id = p.parentid
left join yourtable c on p.id = c.parentid
where gp.parentid is null
there is a ton of information related to hierarchical queries, but nothing including self-joins AND hierarchical queries
您不需要两者,分层查询 是 self-join。
您可以从分层查询开始,例如:
select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
prior id as pid, prior detail1 as pdetail1,
id as cid, detail1 as cdetail1,
level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid
See the docs 表示 connect_by_root 和 connect_by_isleaf 的意思。您对叶节点感兴趣,但是:
select *
from (
select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
prior id as pid, prior detail1 as pdetail1,
id as cid, detail1 as cdetail1,
level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid
)
where is_leaf = 1;
...没有得到您想要的:
GPID GPDETA PID PDETAI CID CDETAI LVL IS_LEAF
---------- ------ ---------- ------ ---------- ------ ---------- ----------
1 BLAH1 2 BLAH2 3 BLAH3 3 1
1 BLAH1 2 BLAH2 4 BLAH4 3 1
5 BLAH5 6 BLAH6 7 BLAH7 3 1
5 BLAH5 8 BLAH8 10 BLAH10 3 1
5 BLAH5 5 BLAH5 9 BLAH9 2 1
从您的示例输出中,您不希望在最后一行的 parent 列中出现 5/BLAH5,因为它们是 grandparent;您希望将 child 值提升为 parent 状态。不过,您可以稍微操纵 parent 和 child 值:
select gpid, gpdetail1,
case lvl when 2 then cid else pid end as pid,
case lvl when 2 then cdetail1 else pdetail1 end as pdetail1,
case lvl when 2 then null else cid end as cid,
case lvl when 2 then null else cdetail1 end as cdetail1
from (
select connect_by_root (id) as gpid, connect_by_root(detail1) as gpdetail1,
prior id as pid, prior detail1 as pdetail1,
id as cid, detail1 as cdetail1,
level as lvl, connect_by_isleaf as is_leaf
from table1
start with parentid is null
connect by prior id = parentid
)
where is_leaf = 1;
GPID GPDETA PID PDETAI CID CDETAI
---------- ------ ---------- ------ ---------- ------
1 BLAH1 2 BLAH2 3 BLAH3
1 BLAH1 2 BLAH2 4 BLAH4
5 BLAH5 6 BLAH6 7 BLAH7
5 BLAH5 8 BLAH8 10 BLAH10
5 BLAH5 9 BLAH9
但只有三个固定级别,再次加入更容易理解...