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 

 

 

 

在SQL数据库中,`LEFT JOIN`(也称为`LEFT OUTER JOIN`)是一种用于从两个或多个表中检索数据的连接类型。`LEFT JOIN` 的主要特点是返回“左”表中的所有记录,即使在“右”表中没有匹配的行。如果在右表中没有匹配,则结果集中的相关列将包含`NULL`值。 ### LEFT JOIN 的使用场景 - **获取所有左表数据**:当需要确保左表中的所有记录都出现在结果集中时,即使右表中没有匹配的记录,可以使用`LEFT JOIN`。例如,查询所有客户信息,并显示他们的订单,即使某些客户尚未下订单。 - **统计分析**:在进行数据分析时,可以通过`LEFT JOIN`获取左表中的所有数据,并结合右表的某些信息进行统计,例如计算客户未付款的订单总额。 - **数据完整性检查**:`LEFT JOIN` 可以用来查找左表中存在但右表中没有对应记录的数据,例如找出没有订单的客户或没有分配任务的员工。 ### LEFT JOIN 与 INNER JOIN 的区别 - `INNER JOIN` 仅返回两个表中匹配的记录,而 `LEFT JOIN` 会返回左表中的所有记录,即使右表中没有匹配项。 - 如果右表中没有匹配的行,`LEFT JOIN` 的结果中右表的字段将显示为`NULL`,而`INNER JOIN` 则会完全排除这些记录。 ### LEFT JOIN 的语法示例 以下是一个使用 `LEFT JOIN` 的 SQL 查询示例,假设有两个表:`customers` 和 `orders`,其中 `customers` 表包含客户信息,`orders` 表包含订单信息。 ```sql SELECT customers.name, orders.order_id, orders.amount FROM customers LEFT JOIN orders ON customers.customer_id = orders.customer_id; ``` 此查询将返回所有客户的名称以及他们的订单 ID 和金额。如果某个客户没有订单,则 `order_id` 和 `amount` 列将显示为 `NULL`。 ### LEFT JOIN 的性能考虑 - **性能优化**:在使用 `LEFT JOIN` 时,需要注意性能问题,尤其是在处理大型数据集时。如果右表中没有索引,或者连接条件不明确,可能会导致查询性能下降。 - **避免不必要的数据**:如果只需要左表中的部分数据,可以通过 `WHERE` 子句进行过滤,减少不必要的数据处理。 - **替代方案**:在某些情况下,可以使用 `NOT EXISTS` 或 `NOT IN` 来代替 `LEFT JOIN`,具体选择取决于查询需求和数据结构。例如,如果需要查找左表中不存在于右表中的记录,可以使用 `LEFT JOIN` 结合 `IS NULL` 条件。 ### LEFT JOIN 的扩展应用 - **多表连接**:`LEFT JOIN` 可以与其他连接类型结合使用,实现多表连接。例如,可以先对两个表使用 `LEFT JOIN`,然后将结果与第三个表进行 `LEFT JOIN`。 - **模拟 FULL JOIN**:如果需要获取两个表中的所有记录(无论是否有匹配),可以使用 `LEFT JOIN` 和 `RIGHT JOIN` 结合 `UNION` 来模拟 `FULL JOIN`。 ### 示例代码 以下是一个更复杂的 `LEFT JOIN` 示例,涉及三个表:`customers`、`orders` 和 `products`。假设 `orders` 表中包含订单信息,而 `products` 表中包含产品信息。 ```sql SELECT customers.name, orders.order_id, products.product_name FROM customers LEFT JOIN orders ON customers.customer_id = orders.customer_id LEFT JOIN products ON orders.product_id = products.product_id; ``` 此查询将返回所有客户的名称、订单 ID 以及对应的产品名称。如果某个客户没有订单,或者订单中没有对应的产品信息,则相关字段将显示为 `NULL`。 ### LEFT JOIN 的常见问题 - **重复数据**:在某些情况下,`LEFT JOIN` 可能会导致重复数据,尤其是当右表中有多条匹配的记录时。为了避免这种情况,可以在查询中使用 `DISTINCT` 关键字。 - **NULL 值处理**:由于 `LEFT JOIN` 可能会返回 `NULL` 值,因此在后续的数据处理中需要特别注意这些值,避免引发错误或误导性结果。 综上所述,`LEFT JOIN` 是 SQL 中非常有用的工具,特别适用于需要保留左表所有记录的场景。通过合理使用 `LEFT JOIN`,可以有效地处理复杂的数据关联问题[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值