首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

再问: 2个左连接的写法有关问题的原理

2011-12-31 
再问: 2个左连接的写法问题的原理让第二个表与第三个左连接构成一个子查询,然后它与第一个表左连接表定义:

再问: 2个左连接的写法问题的原理
让第二个表与第三个左连接构成一个子查询,然后它与第一个表左连接
表定义:temp6(id,age),temp7(age,age2),temp8(age2,name)
temp6是主表,age是整形字段
下面是我上次问得到的答案,但有点麻烦,因为每次都要子查询
select   temp6.*,t.*   from   temp6
left   join  
(
select   temp7.*,temp8.name   from   temp7   left   join   temp8   on   temp7.age2   =   temp8.age2
)   T
on   temp6.age   =   T.age

根据上次提问的结果,可以如下写:
select   *  
from   temp6  
left   join   temp7   on   temp6.age=temp7.age
left   join   temp8   on   temp7.age=temp8.age2
虽然结果正确,内部机制我还是不太明白,只左连一个比较容易理解,左连2个,第二个是如何被附加到结果里的,今天又做了一个,子连接有2个连接字段,其中一个还要和最外层的表关联,因为对原理不明白,写得晕头转向的。
今天写的是这样的一个:
A表是主表,B表有两个主键,f1,f2,f1存在于A表,f2存在于C表,f1的值又通过参数可以得到,想把B和C左连接到A中,不知怎么写对,瞎写了一个。
select   A.*,C.*  
from   A
left   join   B   on   A.f1=B.f1
left   join   C   on   C.f2=B.f2
where  
A.f1= 'a '
现在的感觉就是乱死了,朦朦胧胧地觉得这样可能是对的,但讲不出道理,谁能解释一下内部的原理啊。谢谢谢谢


[解决办法]

--查询分析器中执行:
--建表table1,table2:
create table table1(id int,name varchar(10))
create table table2(id int,score int)
insert into table1 select 1, 'lee '
insert into table1 select 2, 'zhang '
insert into table1 select 4, 'wang '
insert into table2 select 1,90
insert into table2 select 2,100
insert into table2 select 3,70
如表
-------------------------------------------------
table1|table2|
-------------------------------------------------
idname|idscore|
1lee|190|
2zhang|2100|
4wang|370|
-------------------------------------------------

以下均在查询分析器中执行

一、外连接
1.概念:包括左向外联接、右向外联接或完整外部联接

2.左连接:left join 或 left outer join
(1)左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。
(2)sql语句
select * from table1 left join table2 on table1.id=table2.id
-------------结果-------------
idnameidscore
------------------------------
1lee190
2zhang2100
4wangNULLNULL
------------------------------
注释:包含table1的所有子句,根据指定条件返回table2相应的字段,不符合的以null显示

3.右连接:right join 或 right outer join
(1)右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
(2)sql语句
select * from table1 right join table2 on table1.id=table2.id
-------------结果-------------
idnameidscore
------------------------------
1lee190
2zhang2100
NULLNULL370
------------------------------
注释:包含table2的所有子句,根据指定条件返回table1相应的字段,不符合的以null显示

4.完整外部联接:full join 或 full outer join
(1)完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
(2)sql语句
select * from table1 full join table2 on table1.id=table2.id
-------------结果-------------
idnameidscore
------------------------------
1lee190
2zhang2100
4wangNULLNULL
NULLNULL370
------------------------------
注释:返回左右连接的和(见上左、右连接)

二、内连接
1.概念:内联接是用比较运算符比较要联接列的值的联接

2.内连接:join 或 inner join

3.sql语句
select * from table1 join table2 on table1.id=table2.id
-------------结果-------------
idnameidscore
------------------------------
1lee190
2zhang2100
------------------------------
注释:只返回符合条件的table1和table2的列

4.等价(与下列执行效果相同)
A:select a.*,b.* from table1 a,table2 b where a.id=b.id
B:select * from table1 cross join table2 where table1.id=table2.id (注:cross join后加条件只能用where,不能用on)



三、交叉连接(完全)

1.概念:没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。(table1和table2交叉连接产生3*3=9条记录)

2.交叉连接:cross join (不带条件where...)

3.sql语句
select * from table1 cross join table2
-------------结果-------------
idnameidscore
------------------------------
1lee190
2zhang190
4wang190
1lee2100
2zhang2100
4wang2100
1lee370
2zhang370
4wang370
------------------------------
注释:返回3*3=9条记录,即笛卡尔积

4.等价(与下列执行效果相同)
A:select * from table1,table2




[解决办法]
首先更正一下:一个表不可能有两个主键,除非两个字段合起来作一个主健

left join 一般是用于把外键id(标识形式)值转换为主键实际值(名称形式)
左连接,以左边数据为准,按条件left join 右边的表中在数据在左边没出现,这些数据不会在查询结果中,而左边的数据在右边没出现时则查询结果中会以null值出现。

多次left join 除非用括号改变连接顺序,否则一直以左边查询结果为准,到右边去找符合条件的数据,找到了就用,找不到就用null


[解决办法]
一个表的左连接比较容易理解,关键是左连2个的原理十分混乱。请就这个讲讲吧。
--------------------------------------------
第二次连接的是~~第一次连接的结果~~~~
[解决办法]
SQL的表是一个一个地连接的,如你写的查询,第一个表会左连接第二个表,SQL会针对第一个表的每一行去对应第二个表的所有行,只要附合连接条件的都会被连接上,连接的结果是它们变成一个表了,这个表会保存在内存当中,然后再用它去左连接第三个表,。。。依次下去,直到所有的表都被连接,这时内存中这个表是很大的,然后对它执行where,再执行group,如果你理不清其中的头绪,可以用笔画一下,看看前两个表连接后的结果是什么,再用它去连接第三个表。。。。这样比较笨,但是一目了然
[解决办法]
select a.name,c.name,b.qty from goods a,at_store b,stores c where a.goods_no=b.goods_no and b.store_no=c.store_no----不用相当于inner join 只显示三表中都能对应上的
select a.name,c.name,b.qty from goods a left join at_store b on a.goods_no=b.goods_no left join stores c on b.store_no=c.store_no---这样会把有物品名但没有库存的也显示出来
select a.name,c.name,b.qty from at_store b left join goods a on a.goods_no=b.goods_no left join stores c on b.store_no=c.store_no--只显示有库存的物品名称及仓库名

[解决办法]

goods(goods_no,name):物品表(物品编号,名字),主键(物品编号)
1 TV
2 MP3
3 MP4
4 Bike

at_store(goods_no,store_no,qty):仓库在库情况表(仓库编号,仓库名,在库数量),主键(仓库编号,物品编号)
1 1 200
1 2 400
2 3 800
2 4 800
3 1 500
4 3 600

stores(store_no,name):仓库表(仓库编号,仓库名),主键(仓库编号)
1 dalian
2 beijing
3 wuhan
4 changchun

现在给定一个物品编号,仓库编号,以物品表作主表,左连接另外两个表,查出在库情况,怎么写这个语句?谢谢
------------------------------------------------------
个人理解:create table goods(goods_no int ,name nvarchar(200))
insert into goods select 1, 'TV '
insert into goods select 2, 'MP3 '
insert into goods select 3, 'MP4 '
insert into goods select 4, 'Bike '

create table at_store(goods_no int,store_no int,qty int)
insert into at_store select 1,1,200
insert into at_store select 1,2,400
insert into at_store select 2,3,800
insert into at_store select 2,4,800
insert into at_store select 3,1,500
insert into at_store select 4,3,600

create table stores(store_no int ,name nvarchar(200))
insert into stores select 1, 'dalian '
insert into stores select 2, 'beijing '
insert into stores select 3, 'wuhan '
insert into stores select 4, 'changchun '

select b.name,c.name,a.qty from at_store as a left join goods as b on a.goods_no = b.goods_no
left join stores as c on a.store_no = c.store_no

drop table goods
drop table at_store
drop table stores
说明:我是按照【仓库在库情况表】做为查询的主表,全部都是以【仓库在库情况表】中的值为join的条件。这样你应该能明白了吧

热点排行