MYSQL之join语句使用

SQL语句类型:

DDL数据定义语言 create alter负责数据结构定义与数据库对象定义
TPL 事务处理语言 确保被DML语句影响的表和行得以及时更新,包括开始事务、提交事务、回滚
DCL 数据控制语言 用来设置数据库用户或角色权限,包括GRANT,DENY,REMOVE
DML 数据操作语言 增删改查

/*用到的表*/
DROP TABLE IF EXISTS `friends`;/*悟空朋友表*/
CREATE TABLE `friends` (
  `id` int(3) NOT NULL,/*sql server中不能指定int长度*/
  `user_name` varchar(30) default NULL,
  `type` varchar(30) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `friends` VALUES ('1', '孙悟空', 'friends');
INSERT INTO `friends` VALUES ('2', '牛魔王', 'friends');
INSERT INTO `friends` VALUES ('3', '蛟魔王', 'friends');
INSERT INTO `friends` VALUES ('4', '鹏魔王', 'friends');
INSERT INTO `friends` VALUES ('5', '狮驼王', 'friends');

DROP TABLE IF EXISTS `qujing`;/*取经表*/
CREATE TABLE `qujing` (
  `id` int(3) NOT NULL,
  `user_name` varchar(30) default NULL,
  `type` varchar(30) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `qujing` VALUES ('1', '唐僧', 'qujing');
INSERT INTO `qujing` VALUES ('2', '猪八戒', 'qujing');
INSERT INTO `qujing` VALUES ('3', '孙悟空', 'qujing');
INSERT INTO `qujing` VALUES ('4', '沙僧', 'qujing');

如何使用Join语句
分为5种:内连接(INNER)、全外连接(FULL OUTER)、左外连接(LEFT OUTER)、右外连接(RIGHT OUTER)、交叉连接(CROSS)

内连接:就是抽取两张表的公共部分。

MYSQL之join语句使用_第1张图片

select  a.id,b.user_name
from four_team  a,friends_wikong b
where a.user_name=b.user_name;

注意inner join与非join的区别

select a.user_name,b.id
from friends a
inner join qujing b
on a.user_name=b.user_name;

select a.id,b.user_name
from friends a,qujing b
where a.user_name=b.user_name;

外连接之左外连接:
包含左表中的所有数据,当某个连接维持不在右表中时,新生成的表的右表字段为null,对左表数据的信息进行拓展,增加右表中的字段,当某个连接谓词不在右表中时,新生成的表的右表字段为null

MYSQL之join语句使用_第2张图片

left join 以左表为基础查询。

select *
from qujing a
left join friends b
on a.user_name=b.user_name   
//左外连接,包含左表全部信息,当满足条件时显示右表的信息

where b.user_name is null;   //not in关键字不会使用索引,所以用left join
加上关键字null查找只存在A表而不存在B表的数据

查询时左表中的内容为基准,可以查询左表中特有的数据,例如:查询出民族表中民族名为空的学生的姓名、民族;

select a.name,b.nation  from student a left join nation b on 
a.nation_id=b.id where b.nation is null;

left outer join:包含左表中的所有数据,当某个连接谓词不在右表中时,新生成的表的右表字段为null。做坐标数据的信息进行拓展,增加右表中的字段,当某个连接谓词不在右表时,新生成的表deep右表字段为null

使用left outer join对not in进行优化

select select_expressions
from table a left outer join table b on A.key=B.key
where B.key is null;

表A中不包含表B中的数据。

select select_expression
from table A left outer join table B on A.key=B.key
where B.key is not null;

表A与表B的交集,相当于Inner join

右外连接:
作用与left join相似,但是以右表为基准,包括右表的全部信息

MYSQL之join语句使用_第3张图片

全连接
full join 全连接,可以查出A表和B表的数据集,如果连接谓词在A表中没有找到对应数据,则A表的字段用NULL填充,反之B也一样
除此之外full join可以用来查询两个表交集之外的所有数据,相应的会有很多字段为NULL

MYSQL之join语句使用_第4张图片

重点:Full join是left outer join与right outer join的合集,显示出两张表中的所有数据,当一张表的连接谓词无法满足时,则另一张表的字段在该表中为null。

注意:MYSQL不支持full join
解决方法:通过union将做连接和右连接的结果合并
例:

select  select_expressions
  from table A left outer join table B on A.key=B.key
union all
select  select_expressions
from table A right outer join table B on A.key=B.key;

union会自动删除重复项,刷选出来部分字段的时候要注意了,如果刷选出来得两个字段的值完全相同就会剩下一个。
union all和union不同之处在于union all 会将左右两个查询的结果的所有的资料都列出来,无论资料值有无重复。

交叉连接:
cross join,笛卡尔连接,如果A和B是两个集合,它们的交叉连接就记为A X B。一个表的每个记录与另一个表的所有记录进行连接,形成A.length*B.length个数据项的表。(无需提供ON)

select a.user_name,a.over,b.user_name,b.over
from user1  a
cross  join user2  b

注意:在实际的使用中,要尽量避免产生笛卡尔积的查询,因为很少情况我们会使用到笛卡尔积的查询结果,但是在一些特定的情况下,我们需要笛卡尔积查询我们需要的结果。

使用join更新表:
问题1:如何更新from中的表
/更新过滤条件包含自身的表(在这里是更新两个表都存在的用户‘孙悟空’)/

使用jpin的方式进行联合更新

update  user1
set  over=’齐天大圣’
where  user1.user_name in(
select  b.user_name
from  user1  a  inner  join user2  b  on
a.user_name=b.user_name);  报错,mysql报错,而在sql和oracle中通过

以下代码在mysql通过运行

update  user1  a  join(
select  b.user_name
from  user1  a   join user2  b  on
a.user_name=b.user_name)  b  on  a.user_name=b.user_name set
a.over=’齐天大圣’;
update user1 a inner join user2 b on a.user_name = b.user_name 
set a.over='齐天大圣';

用join优化子查询:
一般子程序写法数据小时,没有多大的影响,如果数据量大,则要消耗大量的查询

优化前:

select  a.user_name,a.over,(select  over from user2  b  where  
a.user_name=b.user_name)  as  over2  from  user1  a;

如果这两张表的记录相当多,那么这个子查询相当于对A标的每一条记录都要进行一次子查询

优化后:

select  a.user_name,a.over,b.over   as  over2
from user1 a
left  join  user2  b  on
a.user_name=b.user_name;

select查询字段中包含子查询,就相当于查询出的每条数据都和子查询字段结合,效率低。
优化方法是用left join将子查询表放右侧,取代掉子查询。

使用join优化聚合查询

问题:如何查询出四人组中打怪最多的日期?

select a.user_name,b.timestr,b.kills
from user1  a  join  user_kills  b
on  a.id=b.user_id
where b.kills=(select max(c.kills) from  user_kills c where  c.user_id=b.user_id)
select * from killscount b join tangtang a on b.user_id = a.id 
order by kills DESC 
select a.user_name,b.timestr,max(b.kills) from tangtang a join killscount b 
on a.id = b.user_id  group by  a.user_name,b.timestr;

优化后的结果:(避免子查询的方式)

select a.user_name,b.timestr,b.kills 
from user1 a 
join user_kills b on a.id = b.user_id 
join user_kills c on c.user_id = b.user_id
GROUP BY a.user_name,b.timestr,b.kills
HAVING b.kills = max(c.kills);

参考视频:http://www.imooc.com/learn/398

你可能感兴趣的:(数据库总结)