从关系代数到SQL
并:
select * from R
union
select * from S;
MySQL支持并运算:
SELECT * FROM (select * from study where course='math') as a
UNION
SELECT * FROM (select * from study where course='english') as b;
交:
select * from R
intersect
select * from S;
这里需要补充一下,MySQL不支持intersect语句,我也是后来才知道,那么如何弥补这一缺陷呢?比如我想知道同时选择了英语和数学的学生信息,study关系如下:
方法1:inner join … using()
select * from (select * from study where course='math') as a
inner join
(select * from study where course='english') as b
using(sno);
方法2:inner join … on…
SELECT * from (SELECT * from study where course = 'math') as a
INNER JOIN
(SELECT * from study WHERE course = 'english') as b
on a.sno=b.sno;
差:
select * from R
except
select * from S;
同样MySQL不支持差运算,如何弥补呢?还是上面交运算中的关系,我现在利用它生成一个子关系a,然后从原关系中选出属于原关系而不属于a关系的元组:
select * from study
left outer JOIN
(select * from study where course = 'math') as a
on study.sno=a.sno
where a.sno is NULL;
确实MySQL在实现这个的时候会比较麻烦,自己在实现的时候如果选择的是左外连接,那么右边的关系连接过来很可能会有空值,我们就可以利用空值来选择需要的元组了。
笛卡尔积:
select * from R, S;
# 或者:
select * from R
cross join
s;
(选择)sigma_c®:
select * from R where c;
(投影)projection_L®:
select L from R;
projection_L(sigma_c®):
select L from R where c;
等值连接:
select * from R
join
S
on
R.A = S.B;
例如:现有两个关系pc和laptop如下:
发现pc的model1010和laptop的price1010值相等,下面我们将pc和laptop两个关系的属性model和price进行等值连接:
结果如下:
自然连接:
select * from study NATURAL JOIN
(select * from study where course='english') as b;
注意自然连接和等值连接的条件不同,自然连接必须要两个关系中相等的属性。
这里使用的关系是上面提到的study关系,利用study关系生成一个新的子关系a,求自然连接:
自然连接natural join容易和nature join弄混,如果输入的是nature join结果将截然不同:
这里的nature join 倒是和上面介绍的的笛卡尔积结果一样的。
自然连接还有两个变体,左自然连接、右自然连接:
可以发现,左自然连接实现的功能是在自然连接的结果关系列表的基础上,将左边列表减去右边列表后剩余的部分又加了过来(要注意我所测试的例子的特点:左边的关系包含右边的关系)。看看右自然连接:
发现在左边关系包含右边关系的时候,右自然连接的结果和右边关系一样。
左外连接:
select * from R
left outer join
S
on
c;
发现最终结果集的每个元组都是原来的pc各元组,只是属性增加了,增加的是laptop的各属性,如果两个元组的price相等,就将laptop的数据显示出来,不相等的设置为null
右外连接:
select * from R
right outer join
S
on
c;
全连接:
select * from
pc full join laptop;
去重操作:
select distinct * from R;
排序操作:
select * from R
order by
L;
可能你会问为什么price并不是从小到大排序的?因为这里的数据全部是字符型的,看每一个price的第一个数字,它是符合从小到大的。
聚集操作符:
count # 计数
max # 求最大值
min # 求最小值
avg # 求平均值
sum # 求和
分组操作符:
select L, Fun from R
group by
L;
分组操作符常常和聚集操作符连用,这里的fun就是聚集操作符
如果想在分组操作符的前提下加前提条件,不能使用where关键字,只能使用having :
select L, Fun from R
group by
L
having L > 200;
同样,这里因为数据类型是char类型,所以出来的是9开头的数据
删除操作:
delete from R where a > 20;
将R关系中,a属性大于20的值删除掉。
插入操作:
insert into R(a, b)
values(111, 222);
这里要注意的是,比如R有(a, b, c)三个属性,插入操作不用将所有的属性都赋值,比如上面就将a, b赋值,没有赋值的默认为NULL, 下面的values列表就要和上面的(a, b)对应。
更新操作:
update R set c=333 where a=111;
这里对插入的一个元组的属性c进行更新
现在我想使用update实现将如下的关系中的‘学院代号’属性前面加个‘3’:
这里每一个属性列的域如下:
可能你会这么玩:
update 学院 set 学院代号 = 学院代号 + '3';
可是MySQL中不支持+来连接字符型数据,这样操作不会报错,但是最终的结果与你想的不一样:
统统加3,其实我一开始看到这里挺兴奋的,能将字符型转换为数字,然后我试了一下减乘除,都是支持的:
这里的变化是从前面已经加了3之后变过来的
执行如下语句可以实现在“学院代号”属性后面加上3:
还要补充一点的是不能使用update语句的时候,set后面的属性和where后面的属性相等:
我本来想通过这样将price改一下,但是报错了。
还有就是,如果在varchar类型的数据中,里面都是数字,引用的时候不加引号也是可以的(表中所有数据的类型是varchar类型的):