查询 SQL 中的分层数据
Querying hierarchical data in SQL
如何编写递归 SQL 查询,将不同层次的层次关系显示为单独的结果?
我的数据库 (Container
) 中有一个 table,它与自身具有层次关系(任何容器都可以有多个内部容器)。我正在尝试创建一个视图,显示每个容器及其所有外部(不仅仅是它的直接外部)以及内部容器的深度。例如:
如果我的容器 table 中有以下记录:
- Id: 1 outerId: null
- Id: 2 outerId: 1
- Id: 3 outerId: 1
- Id: 4 outerId: 2
- Id: 5 outerid: 4
我希望视图显示:
- innerId: 2 outerId:1 lvl:1
- innerId: 3 outerId:1 lvl:1
- innerId: 4 outerId:1 lvl:2
- innerId: 4 outerId:2 lvl:1
- innerId: 5 outerId:1 lvl:3
- innerId: 5 outerId:2 lvl:2
- innerId: 5 outerId:4 lvl:4
没有
- 编号:2 路径:1
- 编号:3 路径:1
- 编号:4 路径:1,2
- 编号:5 路径:1,2,4
基本上,我希望能够通过执行 select innerId from v_MyView where outerId = @outer_id
找出特定容器中的内部容器,并通过执行 select outerId from v_MyView where innerId = @inner_id
找出特定容器中的容器
更新
我正在使用 SQL Server 2012,而且我非常熟悉递归 CTE。我遇到的问题不是我不知道如何编写递归 CTE,而是我需要输出在多行中而不是视图中的连接字段。
这是我已有的:
with MYCTE as
(
select
Id,
Cast(null as varchar(max)) as cntr_path,
0 as lvl
from Container
where Container.outerId is null
union all
select
Container.Id,
IsNull(cntr_path + ',','') + '[' + cast(Container.outerId as varchar(max)) + ']',
lvl + 1
from Container join MYCTE
on Container.outerId = MYCTE.Id
)
select * from MYCTE where cntr_path is not null
但这每个内部容器只产生一行。我想要的是每个外部容器每个内部容器一行
我想描述我想要的视图的最佳方式是 "linking table" 将每个外部容器与其每个内部容器联系起来 - "outerId" 和 "innerId" 像外键一样(都指向 Container 中的 Id)。
如果您使用的是 SQL 服务器,请查看此 Microsoft link。它详细介绍了递归通用 Table 表达式。
在 Oracle 中,这是描述 Hierarchical Queries 的 link。
MySQL hierarchical queries.
文章中给出的示例将为您提供解决问题的必要垫脚石。
睡了一会儿之后,我意识到我错误地识别了我的递归 CTE 的锚点。而不是最外面的容器是我的锚点(如我更新的示例),锚点应该是每个带有外部容器的容器:
select
Id as InnerId,
Container.outerId as OuterId
1 as lvl
from Container
这构成了我的 CTE 的递归部分:
union all
select
MYCTE.InnerId,
Container.OuterId
lvl + 1
from Container join MYCTE
on Container.Id = MYCTE.OuterId
where Container.OuterId is not null
如何编写递归 SQL 查询,将不同层次的层次关系显示为单独的结果?
我的数据库 (Container
) 中有一个 table,它与自身具有层次关系(任何容器都可以有多个内部容器)。我正在尝试创建一个视图,显示每个容器及其所有外部(不仅仅是它的直接外部)以及内部容器的深度。例如:
如果我的容器 table 中有以下记录:
- Id: 1 outerId: null
- Id: 2 outerId: 1
- Id: 3 outerId: 1
- Id: 4 outerId: 2
- Id: 5 outerid: 4
我希望视图显示:
- innerId: 2 outerId:1 lvl:1
- innerId: 3 outerId:1 lvl:1
- innerId: 4 outerId:1 lvl:2
- innerId: 4 outerId:2 lvl:1
- innerId: 5 outerId:1 lvl:3
- innerId: 5 outerId:2 lvl:2
- innerId: 5 outerId:4 lvl:4
没有
- 编号:2 路径:1
- 编号:3 路径:1
- 编号:4 路径:1,2
- 编号:5 路径:1,2,4
基本上,我希望能够通过执行 select innerId from v_MyView where outerId = @outer_id
找出特定容器中的内部容器,并通过执行 select outerId from v_MyView where innerId = @inner_id
找出特定容器中的容器
更新
我正在使用 SQL Server 2012,而且我非常熟悉递归 CTE。我遇到的问题不是我不知道如何编写递归 CTE,而是我需要输出在多行中而不是视图中的连接字段。
这是我已有的:
with MYCTE as
(
select
Id,
Cast(null as varchar(max)) as cntr_path,
0 as lvl
from Container
where Container.outerId is null
union all
select
Container.Id,
IsNull(cntr_path + ',','') + '[' + cast(Container.outerId as varchar(max)) + ']',
lvl + 1
from Container join MYCTE
on Container.outerId = MYCTE.Id
)
select * from MYCTE where cntr_path is not null
但这每个内部容器只产生一行。我想要的是每个外部容器每个内部容器一行
我想描述我想要的视图的最佳方式是 "linking table" 将每个外部容器与其每个内部容器联系起来 - "outerId" 和 "innerId" 像外键一样(都指向 Container 中的 Id)。
如果您使用的是 SQL 服务器,请查看此 Microsoft link。它详细介绍了递归通用 Table 表达式。
在 Oracle 中,这是描述 Hierarchical Queries 的 link。
MySQL hierarchical queries.
文章中给出的示例将为您提供解决问题的必要垫脚石。
睡了一会儿之后,我意识到我错误地识别了我的递归 CTE 的锚点。而不是最外面的容器是我的锚点(如我更新的示例),锚点应该是每个带有外部容器的容器:
select
Id as InnerId,
Container.outerId as OuterId
1 as lvl
from Container
这构成了我的 CTE 的递归部分:
union all
select
MYCTE.InnerId,
Container.OuterId
lvl + 1
from Container join MYCTE
on Container.Id = MYCTE.OuterId
where Container.OuterId is not null