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)
内连接:就是抽取两张表的公共部分。
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
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相似,但是以右表为基准,包括右表的全部信息
全连接
full join 全连接,可以查出A表和B表的数据集,如果连接谓词在A表中没有找到对应数据,则A表的字段用NULL填充,反之B也一样
除此之外full join可以用来查询两个表交集之外的所有数据,相应的会有很多字段为NULL
重点: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