数据库SQL练习(一)

好久没有复习SQL语句了,今天简单温习一下。

SQL语句执行顺序

语法顺序:select–from–where–group by–having–order by
执行顺序:from–where–group by–having–select–order by
(select的顺序与语法顺序稍微不一样)

from: 从哪个数据表检索数据
where: 过滤表中数据的条件
group by: 如何将上面过滤出的数据分组
having: 对上面group by已经分组的数据进行过滤的条件
select: 查看结果集中的哪个列,或列的计算结果
order by :按照什么样的顺序来查看返回的数据


以下是祖传的数据练习样例,想学习的可以尝试写一写

简单的数据库使用情景

数据库对象

  1. 用SQL命令创建三张表:Sailors、Boats、Reserves

具体信息如下:
Sailors(sid char(10),sname char(20),rating int,age int),
其中sid是主关键字,sid表示水手的编号,sname表示水手的姓名,rating表示水手的级别,age表示水手的年龄。

CREATE TABLE `sailors` (
  `sid` char(10) NOT NULL,
  `sname` char(20) NOT NULL,
  `rating` int(11) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`sid`)
) 

Boats(bid char(10),bname char(20),color char(10)),其中bid表示船的编号是主关键字,bname是船的名字,color是船的颜色

CREATE TABLE `boats` (
  `bid` char(10) NOT NULL,
  `bname` char(20) NOT NULL,
  `color` char(10) NOT NULL,
  PRIMARY KEY (`bid`)
) 

Reserves(sid char(10),bid char(10),rdate date),
Reserves中记录水手在哪天定了那只船,其中sid是指向Sailors的外关键字,bid是指向Boats的外关键字,(sid,bid,rdate)合起来构成Reserves的主关键字。当sailors或Boats中的相关记录被删除时要求Reservers中的记录也被联带删除。

CREATE TABLE `reserves` (
  `sid` char(10) NOT NULL,
  `rdate` date NOT NULL,
  `bid` char(20) NOT NULL,
  PRIMARY KEY (`sid`,`rdate`,`bid`),
  KEY `bid_idx` (`bid`),
  CONSTRAINT `bid` FOREIGN KEY (`bid`) REFERENCES `boats` (`bid`) ON DELETE CASCADE,
  CONSTRAINT `sid` FOREIGN KEY (`sid`) REFERENCES `sailors` (`sid`) ON DELETE CASCADE
)
/*constraint 外键名 foreign key 外键字段 references 主表名(关联字段) [主表记录删除时的动作] [主表记录更新时的动作]
ON DELETE、ON UPDATE表示事件触发限制,可设参数:
RESTRICT(限制外表中的外键改动,默认值)
CASCADE(跟随外键改动,同删/同更新)
SET NULL(设空值)
SET DEFAULT(设默认值)
NO ACTION(无动作,默认的)
*/
  1. 在以上三表中插入数据,这里给出我的插入:

INSERT INTO 语句
INSERT INTO 语句用于向表格中插入新的行。

语法
INSERT INTO 表名称 VALUES (值1, 值2,…)

指定所要插入数据的列:
INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,…)

//sailors 表
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("22","dustin",7,45);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("58","rusty",10,35);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("29","brustus",1,33);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("64","horatio",7,35);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("31","lubber",8,56);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("71","zorba",10,35);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("32","andy",8,26);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("74","horatio",9,35);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("85","art",3,26);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("96","frodo",3,26);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("86","john",1,17);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("98","tom",3,17);
INSERT INTO Sailors(sid ,sname,rating,age)
VALUES("95","bob",3,64);
//Boats 表
INSERT INTO Boats(bid,bname,color)
VALUES("101","A","red");
INSERT INTO Boats(bid,bname,color)
VALUES("105","E","red");
INSERT INTO Boats(bid,bname,color)
VALUES("102","B","green");
INSERT INTO Boats(bid,bname,color)
VALUES("106","F","blue");
INSERT INTO Boats(bid,bname,color)
VALUES("103","C","blue");
INSERT INTO Boats(bid,bname,color)
VALUES("107","G","green");
INSERT INTO Boats(bid,bname,color)
VALUES("104","D","white");
//Reserves 表
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","101","2010-01-08");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","101","2010-04-07");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","102","2010-01-09");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","105","2010-05-01");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("29","103","2010-01-09");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","106","2010-06-18");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("31","102","2010-02-11");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","107","2010-07-09");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","104","2010-03-08");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("31","106","2010-08-06");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("22","103","2010-03-10");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("32","105","2010-08-06");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("32","105","2010-03-11");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("29","104","2010-08-07");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("32","106","2010-03-18");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("64","103","2010-09-05");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("32","102","2010-03-19");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("58","102","2010-09-09");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("58","104","2010-03-20");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("64","104","2010-11-03");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("64","105","2010-03-20");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("64","105","2010-11-04");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("95","101","2010-04-02");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("31","106","2010-12-06");
INSERT INTO Reserves(sid,bid,rdate)
VALUES("85","102","2010-04-05");*/

一些简单CURD操作(Create Update Retrieve Delete)

  1. 查找定了103号船的水手
SELECT s.*,r.bid
FROM reserves r,sailors s
WHERE r.bid = 103 AND s.sid = r.sid
//简单使用WHERE过滤即可

在这里插入图片描述

  1. 查找定了红色船水手的姓名
SELECT DISTINCT S.sname 
FROM sailors S ,reserves R,boats B
WHERE S.sid=R.sid AND R.bid=B.bid AND B.color="red" 
//注:distinct 意思是将两条完全相同的纪录变为一条

在这里插入图片描述

  1. 将年龄小于30的水手级别增加1.
    更新操作:
    UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值

    注:where用来限制更新哪些行,set后面用,分隔可以更新多列
    varchar等字符串的拼接更新不用+,而用concat
    CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串

// update 
UPDATE SAILORS S
SET S.rating = S.rating + 1
WHERE S.age < 30 ;

/*
若遇到以下错误:
Error Code: 1175 You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column”
Workbench的安全设置不允许我们在没有修改主键的情况下修改table,
我们通过设置就可以进行处理。具体操作是在workbench的菜单栏点击“edit-->Preferences”,
然后会弹出对话框“workbench preferences“,
在“workbench”左边栏点击“SQL Editor”,
会看到最后一行是“Safe Updates……”是打钩的,
我们只要缺消打钩应用即可
*/
  1. 删除名字叫lubber的水手的定船信息.
    删除语法:
    DELETE FROM 表名称 WHERE 列名称 = 值
delete
from reserves
where sid = (select sid from sailors where sname ="lubber")
/*
from 后面接一个table
初学者可以使用delete时会类比select的写法,可能写成以下形式
delete
from reserves r,sailor r
where r.sid = s.sid and s.name = "lubbe";
这样是一个语法错误!
*/

一些较复杂CURD操作

  1. 查找定过船而没有定过红色船的水手信息

简单的思路:
先找到订过红色船的水手,然后在所有订了船的水手中取not除掉前者,剩余的即为所求。
(最外面的select是为了获取水手的信息,其实sid在第二个select已经都拿到了)

select *
from sailors S
where S.sid in( select R.sid
				from reserves R
				where R.sid not in(select R.sid
								from reserves R,boats B
								where R.bid = B.bid and B.color="red")  )  

这里涉及到了in操作:
其过程为,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。由于其放弃了索引,改为笛卡尔积+扫描,在内、外表特别大的时候不推荐使用。
select * 打印多余信息,工程上尽量少用

在这里插入图片描述

  1. 查找定过所有船的水手姓名和编号

    exists:指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样,匹配上就将结果放入结果集中,其每次查询外表值是否在内表存在,会尝试使用内表的索引。
    相较于in,in会把B表放在内存里遍历比较,exists会查询数据库索引。通常来说exists性能更优,但是表小的时候in可能效果更佳,具体还是要看应用情况。

select S.sname,S.sid
from sailors S
where not exists(select *  /*不存在有船没被sid定*/
				 from boats B
                 where not exists(select distinct R.bid /*某个水手其订的所有船*/
				                  from reserves R
				                  where R.sid = S.sid and R.bid = B.bid) )

在这里插入图片描述

  1. 查找年龄最大的水手姓名和年龄
    MAX() 函数
    MAX 函数返回一列中的最大值。NULL 值不包括在计算中。
select S.sname,S.age
from sailors S
where S.age = (select max(S.age)
              from sailors S)

在这里插入图片描述

  1. 统计水手表中每个级别组的平均年龄和级别组

    AVG 函数返回数值列的平均值。NULL 值不包括在计算中。

select avg(S.age) as 平均年龄,S.rating as 级别组
from sailors S
group by S.rating
//avg这个对group以后的分组数据取平均值,as的别名依据需求设置

在这里插入图片描述

  1. 统计水手表中每个人数不少于2人的级别组中年满18岁水手的平均年龄和级别组

    分析:对组有要求用having 注意语句执行顺序,先where再group
    count() 函数返回匹配指定条件的行数。
    count()(column_name) 函数返回指定列的值的数目(NULL 不计入):
    count(*)—包括所有列,返回表中的记录数,相当于统计表的行数,在统计结果的时候,记录NULL的记录。
    count(DISTINCT column_name) 函数返回指定列的不同值的数目

select avg(S.age) as 平均年龄,S.rating as 级别组
from sailors S
where S.sid in(select S1.sid
              from sailors S1
              where S1.age > 18)
group by S.rating
having count(1) >= 2

在这里插入图片描述

  1. 统计水手表中人数最少的级别组及人数
    首先得找到分组的数据表用count(),然后用min()取人数最少
    from 中用temp做临时表
select temp.ranks,temp.people
from (select S.rating as ranks,count(*) as people
      from sailors S
      group by S.rating) as temp
	  where temp.people = (select min(temp.people)
						 from (select S.rating as ranks,count(*) as people
			                     from sailors S
								 group by S.rating) as temp);

在这里插入图片描述

补充一点:
当我们需要从数据源上 直接判断数据显示代表的含义的时候 ,就可以在SQL语句中使用 Case When这个函数;

MySQL 的 case when 的语法:
简单函数
CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END

搜索函数
CASE WHEN [expr] THEN [result1]…ELSE [default] END

简单例子:
查询男生、女生的人数;

select 
count(case when student.gender = "男" then 1 end) as "男生人数" ,
count(case when student.gender = "女" then 1 end) as "女生人数" 
from student

按各科平均成绩从低到高和及格率的百分数从高到低顺序;

select score.Course_id as 课程id , avg(score.number) as 平均成绩,
100 * sum(case when score.number >= 60 then 1 else 0 end) / count(*)  as 及格率
from score
group by 课程id
order by 平均成绩 asc,
及格率 desc;
create table sailors( sid char(10) primary key, sname char(20), rating int, age int); create table boats( bid char(10) primary key, bname char(20), color char(10)); create table reserves( sid char(10) , bid char(10) , rdate date, primary key(sid,bid,rdate), foreign key (sid) references sailors(sid) on delete cascade, foreign key (bid) references boats(bid) on delete cascade); insert into sailors(sid,sname,rating,age) values("22","dustin",7,45) ("29","brustus",1,33), ("31","lubber",8,56), ("32","andy",8,26), ("58","rusty",10,35), ("64","horatio",7,35), ("71","zorba",10,35), ("74","horatio",9,35), ("85","art",3,26), ("86","john",1,17), ("95","bob",3,64), ("96","frodo",3,26), ("98","tom",3,17); insert into boats(bid,bname,color) values("101","A","red"), ("102","B","green"), ("103","C","blue"), ("104","D","white") ("105","E","red"), ("106","F","blue"), ("107","G","green"); insert into reserves(sid,bid,rdata) values("22","101","2010-01-08"), ("22","102","2010-01-09"), ("29","103","2010-01-09"), ("31","102","2010-02-11"), ("22","104","2010-03-08"), ("22","103","2010-03-10"), ("32","105","2010-03-11"), ("32","106","2010-03-18"), ("32","102","2010-03-19"), ("58","104","2010-03-20"), ("64","105","2010-03-20"), ("95","101","2010-04-02"), ("85","102","2010-04-05"), ("22","101","2010-04-07"), ("22","105","2010-05-01"), ("22","106","2010-06-18"), ("22","107","2010-07-09"), ("31","106","2010-08-06"), ("32","105","2010-08-06"), ("29","104","2010-08-07"), ("64","103","2010-09-05"), ("58","102","2010-09-09"), ("64","104","2010-11-03"), ("64","105","2010-11-04"), ("31","106","2010-12-0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值