left join

left join 就是以左边的表为基础,扫描右边的表,on .,,and ,,,是条件,如果and后面的约束左边的field则 右边表都符合条件。

左连接是left join 嘛,无非是左边表为基础, 扫描右边表匹配的记录
--按条件 a.uname='mike', 来扫描右边表的记录
--对于右边表的每条记录, 显然 a.uname='mike' 这个条件都是成立.

http://blog.csdn.net/xingfeng0501/article/details/7816703

http://blog.csdn.net/qq_27918787/article/details/52297309

https://www.cnblogs.com/tinachang021/archive/2008/09/25/1298949.html

 

 

数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。

      在使用left jion时,onwhere条件的区别如下:

1 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。

2where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

       假设有两张表:

1 tab1

id size

1 10

2 20

3 30

2 tab2

size name

10 AAA

20 BBB

20 CCC


两条SQL:
1
select * formtab1 left join tab2 on (tab1.size = tab2.size) where tab2.name=’AAA’
2
select * formtab1 left join tab2 on (tab1.size = tab2.size and tab2.name=’AAA’)

第一条SQL的过程:

1、中间表
on条件
tab1.size = tab2.size

tab1.id    tab1.size   tab2.size     tab2.name

1              10                  10              AAA

2             20                    20             BBB

2            20                     20              CCC

3            30                   (null)             (null)

2、再对中间表过滤
where 条件:
tab2.name=’AAA’

tab1.id      tab1.size       tab2.size     tab2.name

1                 10                 10             AAA

第二条SQL的过程:

1、中间表
on条件
tab1.size = tab2.size and tab2.name=’AAA’
(
条件不为真也会返回左表中的记录)

tab1.id      tab1.size        tab2.size       tab2.name

1              10                    10                  AAA

2              20                  (null)              (null)

3              30                   (null)                (null)

     其实以上结果的关键原因就是left join,right join,full join的特殊性,不管on上的条件是否为真都会返回leftright表中的记录full则具有leftright的特性的并集。inner jion没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。

 

 

 

 

 

 

一、概念:

–把left join左边的表的记录全部找出来。系统会先用表A和表B做个笛卡儿积,然后以表A为基表,去掉笛卡儿积中表A部分为NULL的记录。最后形成你的结果。

–进行左连接时,就有涉及到主表、辅表,这时主表条件写在WHERE之后,辅表条件写在ON后面。

二、实例

1、表a结构和数据

table a(id, type):

id     type 

----------------------------------

1      1         

2      1          

3      2     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2、表b结构和数据

table b(id, class):

id    class 

---------------------------------

1      1

2      2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3、SQL语句调用

--sql语句1:

select a.*, b.* from a left join b on a.id = b.id and a.type = 1;

执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2

3        2         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
--sql语句2:

select a.*, b.* from a left join b on a.id = b.id where a.type = 1;

执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            2        2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
--sql语句3:

select a.*, b.* from a left join b on a.id = b.id and b.class = 1;

执行结果为:

a.id    a.type    b.id    b.class

----------------------------------------

1        1            1        1

2        1            

3        2          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

4、总结:

–sql语句1可见,left join 中左表的全部记录将全部被查询显示,on 后面的条件对它不起作用,除非再后面再加上where来进行筛选,这就是sql语句2了。

–由sql语句3可见,on后面的条件中,右表的限制条件将会起作用。

20180815总结,

left join,涉及主表,副表

left join on 后面的条件(无论是对主表的条件还是副表的条件) 不会过滤主表的返回数,(全部返回)

而如果是where 后面再加主表的限制条件,则会过滤 主表的返回数,(不是全部返回了)

left join on 后面的条件如果加在副表上,则会过滤副表的返回条数,主表不影响。如果on 后面的条件加在了主表上,则不会影响主表的返回条数(照样全部返回)

 

因此,where 后面加主表的限制条件,on 后面加副表的限制条件,则最后的返回结果集中将不再是主表全部返回,满足表连接条件的副表全部返回。

如果没有where +主表限制,及on 后面只有连接条件,没有副表的限制条件 则最后的结果集就是我最初学到的left join , 主表全部返回,副表满足连接条件的全部返回。否则,主表的返回条数可以限制,副表的返回结果也可以限制,最后的表就是2张表的都不全,符合我们实际复杂的需求

 

 

 

 

关于数据库中使用 left join on ...and ...和 left join on ....where ...区别,和使用group by 要注意的情况


create table UserAccount
(
   UID int,
   UName varchar(50),
   JoinDate datetime
)


insert into UserAccount values(1,'Jimmy','2006-10-3')
insert into UserAccount values(2,'Jack','2006-10-25')
insert into UserAccount values(3,'Mike','2006-11-13')
insert into UserAccount values(4,'Tom','2006-9-5')


create table ChargeHistory(UId int,ChargeDate datetime,Amount int)

insert into ChargeHistory values(1,'2007-3-1',50)
insert into ChargeHistory values(1,'2007-2-15', 30)
insert into ChargeHistory values(2,'2007-2-1' ,40)
insert into ChargeHistory values(3,'2007-1-15' ,60)
insert into ChargeHistory values(2,'2007-1-15' ,50)
insert into ChargeHistory values(3,'2007-1-1' ,100)
insert into ChargeHistory values(1,'2006-12-20' ,60)


select * from UserAccount
select * from ChargeHistory

1
Jimmy 2006-10-03 00:00:00.000 2
Jack 2006-10-25 00:00:00.000 3
Mike 2006-11-13 00:00:00.000 4
Tom 2006-09-05 00:00:00.000 

1
2007-03-01 00:00:00.000 50 1
2007-02-15 00:00:00.000 30 2
2007-02-01 00:00:00.000 40 3
2007-01-15 00:00:00.000 60 2
2007-01-15 00:00:00.000 50 3
2007-01-01 00:00:00.000 100 1
2006-12-20 00:00:00.000 60 

 

 

假设有一个游戏帐户充值网站

系统内有两个表

UserAccount

 


ChargeHistory
 

 

 

 

1.       建表并填充数据

2.       完成如下操作:

A.     查询用户名为mike的充值记录,包含如下列

   UName,UId,JoinDate,ChargeDate,Amount

B.      查询用户Id为1共充值多少金额.包含

UName,UId,JoinDate,Amount

C.      统计每个用户的充值总额,结果如下

 

 

 

 

 

select A.UID,A.UName,A.JoinDate,B.ChargeDate,B.Amount from UserAccount A
left join ChargeHistory  B on A.UID=B.UID and a.uname='mike' 这里的结果是:不是我们想要的结果因为:

--通过以下结果我们可以看出:左连接是left join 嘛,无非是左边表为基础, 扫描右边表匹配的记录
--按条件 a.uname='mike', 来扫描右边表的记录
--对于右边表的每条记录, 显然 a.uname='mike' 这个条件都是成立.


Jimmy 2006-10-03 00:00:00.000 NULL NULL 2
Jack 2006-10-25 00:00:00.000 NULL NULL 3
Mike 2006-11-13 00:00:00.000 2007-01-15 00:00:00.000 60 3
Mike 2006-11-13 00:00:00.000 2007-01-01 00:00:00.000 100 4
Tom 2006-09-05 00:00:00.000 NULL NULL 

 

 

 

select A.UID,A.UName,A.JoinDate,B.ChargeDate,B.Amount from UserAccount A
left join ChargeHistory  B on A.UID=B.UID where  AME='M.UNAike'所以这里要使用where .where是left join 后筛选结果.

结果:

Mike 2006-11-13 00:00:00.000 2007-01-15 00:00:00.000 60 3
Mike 2006-11-13 00:00:00.000 2007-01-01 00:00:00.000 100 4

--但是inner join 是选择符合条件的数据出来 
select A.UID,A.UName,A.JoinDate,B.ChargeDate,B.Amount from UserAccount A
inner join ChargeHistory  B on A.UID=B.UID and a.uname='mike'

--group by 的操作:
--有函数存在 :sum,count,min,avg,max
--slecect多少个字段,group by 多少个字段

select A.UID,A.UName,A.JoinDate,sum(B.amount) from UserAccount A left join ChargeHistory B ON A.uID=B.UID WHERE A.UID=1  
group by a.uid,A.UName,A.JoinDate

 

--这里还要注意 having的用法:是用来在group by 后再筛选数据的 
select A.UID,A.UName,A.JoinDate,sum(B.amount) from UserAccount A left join ChargeHistory B ON A.uID=B.UID 
group by a.uid,A.UName,A.JoinDate 
having  A.UID=1 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值