AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 34011
Accepted
Biju jose
Biju jose
Asked: 2013-02-03 02:18:56 +0800 CST2013-02-03 02:18:56 +0800 CST 2013-02-03 02:18:56 +0800 CST

剖析连接

  • 772

最近我在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. 首先,他将四列命名为每个级别 1、2、3 等
  2. 每次他离开时加入同一张表 4 次,每次都使用不同的别名
  3. 通过在每个连接上给出条件,表将更改为下一个级别
  4. where条件指定manager

我无法理解的部分是他所做的连接,即使我知道左连接的使用,我们将在其中获取左表的列,如果没有找到匹配项,则在右侧,它将为 NULL。所以我正在寻找一些可视化在这里发生的连接或对这种特定场景的深度连接的一些理解。如果问题不适合这里,我将删除它。我在发布的问题中也问了同样的问题,但没有回复,这就是我提出新问题的原因

sql-server t-sql
  • 1 1 个回答
  • 161 Views

1 个回答

  • Voted
  1. Best Answer
    Andriy M
    2013-02-03T04:25:22+08:002013-02-03T04:25:22+08:00

    首先在没有连接的情况下尝试此查询:

    select  
     level1.res_name as level1
    
    from resource as level1
    
    where isnull(level1.man_id,0)=0
    

    这将返回man_id未引用任何内容的行。换句话说,这只返回最顶层的经理。对于您的特定示例,它的工作方式如下:

    • FROM 子句返回整个表:

      level1.Res_id  level1.Res_name  level1.Man_id
      -------------  ---------------  -------------
      1              sam              3
      2              Biju             4
      3              adrian           NULL
      4              Helen            3
      5              Micah            4
      
    • WHERE 子句只留下一行:

      level1.Res_id  level1.Res_name  level1.Man_id
      -------------  ---------------  -------------
      3              adrian           NULL
      
    • 最后,SELECT 仅从中获取一列:

      level1
      ------
      adrian
      

    像 Chris 的查询一样添加一个自连接,

    select  
     level1.res_name as level1,
     level2.res_name as level2
    
    from resource as level1
    left join resource as level2 on level1.res_id=level2.man_id
    
    where isnull(level1.man_id,0)=0
    

    给你每一位高层经理的直属下属。更具体地说,连接会产生以下行集:

    level1.Res_id  level1.Res_name  level1.Man_id  level2.Res_id  level2.Res_name  level2.Man_id
    -------------  ---------------  -------------  -------------  ---------------  -------------
    1              sam              3              NULL           NULL             NULL
    2              Biju             4              NULL           NULL             NULL
    3              adrian           NULL           1              sam              3
    3              adrian           NULL           4              Helen            3
    4              Helen            3              2              Biju             4
    4              Helen            3              2              Biju             4
    5              Micah            4              NULL           NULL             NULL
    

    WHERE 子句将其过滤为:

    level1.Res_id  level1.Res_name  level1.Man_id  level2.Res_id  level2.Res_name  level2.Man_id
    -------------  ---------------  -------------  -------------  ---------------  -------------
    3              adrian           NULL           1              sam              3
    3              adrian           NULL           4              Helen            3
    

    最后 SELECT 子句只返回名称:

    level1  level2
    ------  ------
    adrian  sam
    adrian  Helen
    

    以同样的方式,再添加一个连接,如下所示:

    select  
     level1.res_name as level1,
     level2.res_name as level2,
     level3.res_name as level3
    
    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
    
    where isnull(level1.man_id,0)=0
    

    带来下一级的下属:

    • 这是将表的第三个实例连接到第一个连接结果的结果:

      1.Res_id  1.Res_name  1.Man_id  2.Res_id  2.Res_name  2.Man_id  3.Res_id  3.Res_name  3.Man_id
      --------  ----------  --------  --------  ----------  --------  --------  ----------  --------
      1         sam         3         NULL      NULL        NULL      NULL      NULL        NULL
      2         Biju        4         NULL      NULL        NULL      NULL      NULL        NULL
      3         adrian      NULL      1         sam         3         NULL      NULL        NULL
      3         adrian      NULL      4         Helen       3         2         Biju        4
      3         adrian      NULL      4         Helen       3         5         Micah       4
      4         Helen       3         2         Biju        4         NULL      NULL        NULL
      4         Helen       3         5         Micah       4         NULL      NULL        NULL
      5         Micah       4         NULL      NULL        NULL      NULL      NULL        NULL
      

      (为方便起见,我缩短了表格别名:1代表level1、2forlevel2和3for level3)

    • 这是 WHERE 过滤器之后剩下的:

      1.Res_id  1.Res_name  1.Man_id  2.Res_id  2.Res_name  2.Man_id  3.Res_id  3.Res_name  3.Man_id
      --------  ----------  --------  --------  ----------  --------  --------  ----------  --------
      3         adrian      NULL      1         sam         3         NULL      NULL        NULL
      3         adrian      NULL      4         Helen       3         2         Biju        4
      3         adrian      NULL      4         Helen       3         5         Micah       4
      
    • 这就是 SELECT 从上面提取并返回给你的内容:

      level1  level2  level3
      ------  ------  ------
      adrian  sam     NULL
      adrian  Helen   Biju
      adrian  Helen   Micah
      

    其余的连接也是如此。但是,对于您的示例,将不再有行,因为表中的层次结构不会超过两层。因此,Chris 的原始查询中的其他两列level4和level5将返回 NULL:

    level1  level2  level3  level4  level5
    ------  ------  ------  ------  ------
    adrian  sam     NULL    NULL    NULL
    adrian  Helen   Biju    NULL    NULL
    adrian  Helen   Micah   NULL    NULL
    

    如果 Chris 关于大多数情况下四个连接就足够的假设不适用于您的特定情况(当然,我不是指您问题中的简单示例),您可以使用相同的模式加入更多的自连接。

    • 6

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve