最近我在dba.stackexchange中问了一个问题,这个问题是关于 sql 中的数据层次结构的,一个叫chris allen的人回答了这个问题,我真的很喜欢它,但是当我试图更多地理解这个查询时,我感到困惑。
这是查询:
Res_id Res_name Man_id
1 sam 3
2 Biju 4
3 adrian Null
4 Helen 3
5 Micah 4
select
level1.res_name as level1,
level2.res_name as level2,
level3.res_name as level3,
level4.res_name as level4,
level5.res_name as level5
from resource as level1
left join resource as level2 on level1.res_id=level2.man_id
left join resource as level3 on level2.res_id=level3.man_id
left join resource as level4 on level3.res_id=level4.man_id
left join resource as level5 on level4.res_id=level5.man_id
where isnull(level1.man_id,0)=0
我做了好几种破解方法,都是徒劳。我想我错过了一些很好的东西我的发现如下
- 首先,他将四列命名为每个级别 1、2、3 等
- 每次他离开时加入同一张表 4 次,每次都使用不同的别名
- 通过在每个连接上给出条件,表将更改为下一个级别
- where条件指定manager
我无法理解的部分是他所做的连接,即使我知道左连接的使用,我们将在其中获取左表的列,如果没有找到匹配项,则在右侧,它将为 NULL。所以我正在寻找一些可视化在这里发生的连接或对这种特定场景的深度连接的一些理解。如果问题不适合这里,我将删除它。我在发布的问题中也问了同样的问题,但没有回复,这就是我提出新问题的原因
首先在没有连接的情况下尝试此查询:
这将返回
man_id
未引用任何内容的行。换句话说,这只返回最顶层的经理。对于您的特定示例,它的工作方式如下:FROM 子句返回整个表:
WHERE 子句只留下一行:
最后,SELECT 仅从中获取一列:
像 Chris 的查询一样添加一个自连接,
给你每一位高层经理的直属下属。更具体地说,连接会产生以下行集:
WHERE 子句将其过滤为:
最后 SELECT 子句只返回名称:
以同样的方式,再添加一个连接,如下所示:
带来下一级的下属:
这是将表的第三个实例连接到第一个连接结果的结果:
(为方便起见,我缩短了表格别名:
1
代表level1
、2
forlevel2
和3
forlevel3
)这是 WHERE 过滤器之后剩下的:
这就是 SELECT 从上面提取并返回给你的内容:
其余的连接也是如此。但是,对于您的示例,将不再有行,因为表中的层次结构不会超过两层。因此,Chris 的原始查询中的其他两列
level4
和level5
将返回 NULL:如果 Chris 关于大多数情况下四个连接就足够的假设不适用于您的特定情况(当然,我不是指您问题中的简单示例),您可以使用相同的模式加入更多的自连接。