Heim  >  Artikel  >  Datenbank  >  通过一个小问题来学习SQL关联查询

通过一个小问题来学习SQL关联查询

WBOY
WBOYOriginal
2016-06-07 17:39:19961Durchsuche

原话题: 是关于一个left join的,没有技术难度,但不想清楚不一定能回答出正确答案来: TabA表有三个字段Id,Col1,Col2 且里面有一条数据1,1,2 TabB表有两个字段Id,Col1且里面有四条数据 问题: 如下语句会返回多少条数据? 在不写测试脚本的情况下 ,如果你

原话题:

  

是关于一个left join的,没有技术难度,但不想清楚不一定能回答出正确答案来:

   TabA表有三个字段Id,Col1,Col2 且里面有一条数据1,1,2

   TabB表有两个字段Id,Col1且里面有四条数据

问题:

如下语句会返回多少条数据? 在不写测试脚本的情况下,如果你能在5分钟内准备回答出答案,且能说出些所以然来(及不是凭感觉猜出来的结果),那么请继续看后面的问题。

Select * from TabA a Left join TabB b1 on a.Col1=b1.Col1 Left join TabB b2 on a.Col2=b2.Col1

延深问题:

现在表A多增加一条数据2,3,4 ,此时再运行上面的语句会几条数据?如果你能在2分钟内回答出正常答案,那么请继续看后面的问题。

理论问题:

我发现就上面这个问题不少人回答不正确,这其中也包括我自己。为什么如此简单的问题往往会回答错误,我认为可能有如下原因:

对于第一种情况的人,短时间内无法解决,只有通过自身的学习来补救,对于第二种情况的人就需要稍微学习一些基本的理论知识就够用,对于第三种情况的人是一个态度问题。

left join的概念

 

简单来讲就是以左表做为外层循环表,每条每条去内层表去查找匹配记录,如果找到就返回join好的值,如果没找到返回外层表的值,内层表统一赋值为null。这里之所以说成简单来讲,是因为我是拿嵌套循环的例子来分析,因为这比较容易让非SQL方面的程序员明白,毕竟对于.net程序员来讲编写双层或者多层循环的例子会很多。而对于hash匹配以及合并联接的应用场景在.net程序中相对较少,类似如下的双层循环。

foreach(var colA in tabA) { foreach(var colB in tabB) { if(colA==colB) { ...... } } }

 这里需要注意下,上面说到的外层表的记录循环去内层表查找时,这里有个问题,看这条语句:

Select * from TabA a Left join TabB b1 on a.Col1=b1.Col1

 这里的TabA 就是我这里讲的外层表,TabB就是内层表,外层表就一行数据,内层表有4行数据,从上面给出的数据来看,用来做等值判断的条件是外层表的Col1字段与内层表的Col1字段,拿外层表的Cole=1这行数据去内层表查询时,内层表的第一条数据符合条件,其它三条不符合,此时的结果会是下面的哪一种呢?

  • 4条记录
  • a.Id  a.Col1  a.Col2 b.Id  b.Col1

    1      1         2          1     1

    1      1         2          null  null

    1      1         2          null  null

    1      1         2          null  null

  • 一条记录
  • a.Id  a.Col1  a.Col2  b.Id  b.Col1

    1       1        1          2      1    

    这要理解当在内层表中找到数据以及找不到数据的区别,我们拿外层表Col1=1这条数据去内层表查找时,需要查找4次,其中有一条符合,三条不符合,这说明找到了匹配数据,所以只返回匹配的数据行,即一条数据,而不会出现上面的第一种结果返回4条数据。

    这是我当时遇到这个问题时产生的误解。

    再看后面的那个left join

    Select * from TabA a Left join TabB b1 on a.Col1=b1.Col1 Left join TabB b2 on a.Col2=b2.Col1

     容易产生的问题,再进行第二次left join 的时候,外层表是TabA原始表呢还是第一次left join 之后的结果集呢? 看下我列出来的表头,就很容易理解了,这里的a.Col2就是第一次left join后的结果集。( a.Id  a.Col1  a.Col2 b.Id  b.Col1)

    我们可以做下测试,这里使用inner join来做测试,,因为这加容易比较出差异,运行下面的语句,此时TabA中有两条数据,就是上面延深问题中添加的2,3,4这条。

    Select * from TabA a inner join TabB b1 on a.Col1=b1.Col1 inner join TabB b2 on a.Col2=b2.Col1

     分两步来看:

    Select * from TabA a inner join TabB b1 on a.Col1=b1.Col1

     这里只会返回一条数据,因为inner join返回的交集。 

    a.Id  a.Col1  a.Col2 b.Id  b.Col1

    1     1           2        1     1

    如果第二次join 时,如果连接的是原始表TablA,那么循环查询的次数应该是TabA的总条数2,但从下面的执行计划图可以分析出执行顺序。

    Stellungnahme:
    Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn