MySQL面试题(四)

上一篇文章介绍了MySQL高性能索引,本文将介绍MySQL的SQL语句编写。

首先看一道真题

有A(id,sex,par,c1,c2),B(id,age,c1,c2)两张表,其中A.id与B.id关联,现在要求写出一条SQL语句,将B中age>50的记录的c1,c2更新到A表中同一记录中的c1,c2字段中

考点分析

这道题主要考察的是MySQL的关联UPDATE语句

延伸考点:

MySQL的关联查询语句

MySQL的关联UPDATE语句

针对刚才这道题,答案可以是如下两种形式的写法:

UPDATE A,B SET A.c1 = B.c1, A.c2 = B.c2 WHERE A.id = B.id

UPDATE A INNER JOIN B ON A.id=B.id SET A.c1 = B.c1,A.c2=B.c2

再加上B中age>50的条件:

UPDATE A,B set A.c1 = B.c1, A.c2 = B.c2 WHERE A.id = B.id and B.age > 50;

UPDATE A INNER JOIN B ON A.id = B.id set A.c1 = B.c1,A.c2 = B.c2 WHERE B.age > 50

MySQL的关联查询语句

六种关联查询

交叉连接(CROSS JOIN)

内连接(INNER JOIN)

外连接(LEFT JOIN/RIGHT JOIN)

联合查询(UNION与UNION ALL)

全连接(FULL JOIN)

交叉连接(CROSS JOIN)

SELECT * FROM A,B(,C)或者

SELECT * FROM A CROSS JOIN B (CROSS JOIN C)

没有任何关联条件,结果是笛卡尔积,结果集会很大,没有意义,很少使用

内连接(INNER JOIN)

SELECT * FROM A,B WHERE A.id=B.id或者

SELECT * FROM A INNER JOIN B ON A.id=B.id

多表中同时符合某种条件的数据记录的集合,INNER JOIN可以缩写为JOIN

内连接分为三类

等值连接:ON A.id=B.id

不等值连接:ON A.id > B.id

自连接:SELECT * FROM A T1 INNER JOIN A T2 ON T1.id=T2.pid

外连接(LEFT JOIN/RIGHT JOIN)

左外连接:LEFT OUTER JOIN, 以左表为主,先查询出左表,按照ON后的关联条件匹配右表,没有匹配到的用NULL填充,可以简写成LEFT JOIN

右外连接:RIGHT OUTER JOIN, 以右表为主,先查询出右表,按照ON后的关联条件匹配左表,没有匹配到的用NULL填充,可以简写成RIGHT JOIN

LEFT JOIN,RIGHT JOIN,INNER JOIN的区别?

联合查询(UNION与UNION ALL)

SELECT * FROM A UNION SELECT * FROM B UNION ...

就是把多个结果集集中在一起,UNION前的结果为基准,需要注意的是联合查询的列数要相等,相同的记录行会合并

如果使用UNION ALL,不会合并重复的记录行

效率 UNION 高于 UNION ALL

全连接(FULL JOIN)

MySQL不支持全连接

可以使用LEFT JOIN 和UNION和RIGHT JOIN联合使用

SELECT * FROM A LEFT JOIN B ON A.id=B.id UNION

SELECT * FROM A RIGHT JOIN B ON A.id=B.id

嵌套查询

用一条SQL语句得结果作为另外一条SQL语句得条件,效率不好把握

SELECT * FROM A WHERE id IN (SELECT id FROM B)

解题方法

根据考题要搞清楚表的结果和多表之间的关系,根据想要的结果思考使用那种关联方式,通常把要查询的列先写出来,然后分析这些列都属于哪些表,才考虑使用关联查询

真题

问题1:

为了记录足球比赛的结果,设计表如下:

team:参赛队伍表

match:赛程表

其中,match赛程表中的hostTeamID与guestTeamID都和team表中的teamID关联,查询2006-6-1到2006-7-1之间举行的所有比赛,并且用以下形式列出:拜仁 2:0 不莱梅 2006-6-21

答:

首先列出需要查询的列:

表team

teamID teamName

表match

match ID

hostTeamID

guestTeamID

matchTime matchResult

其次列出结果列:

主队 结果 客对 时间

初步写一个基础的SQL:

SELECT hostTeamID,matchResult,matchTime guestTeamID from match where matchTime between "2006-6-1" and "2006-7-1";

通过外键联表,完成最终SQL:

select t1.teamName,m.matchResult,t2.teamName,m.matchTime from match as m left join team as t1 on m.hostTeamID = t1.teamID, left join team t2 on m.guestTeamID=t2.guestTeamID where m.matchTime between "2006-6-1" and "2006-7-1"

问题2:UNION与UNION ALL的区别?

答:

如果使用UNION ALL,不会合并重复的记录行

效率 UNION 高于 UNION ALL


问题3:

一个6亿的表a,一个3亿的表b,通过外键tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录。

答:

1、如果A表TID是自增长,并且是连续的,B表的ID为索引

select * from a,b where a.tid = b.id and a.tid>50000 limit 200;

2、如果A表的TID不是连续的,那么就需要使用覆盖索引.TID要么是主键,要么是辅助索引,B表ID也需要有索引。

select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;

问题4:拷贝表( 拷贝数据, 源表名:a 目标表名:b)

答:

insert into b(a, b, c) select d,e,f from a;

问题5:

Student(S#,Sname,Sage,Ssex) 学生表

Course(C#,Cname,T#) 课程表

SC(S#,C#,score) 成绩表

Teacher(T#,Tname) 教师表

查询没学过“叶平”老师课的同学的学号、姓名

答:

select Student.S#,Student.Sname

from Student

where S# not in (select distinct( SC.S#) from SC,Course,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname=’叶平’);

问题6:随机取出10条数据

答:

SELECT * FROM users WHERE id >= ((SELECT MAX(id) FROM users)-(SELECT MIN(id) FROM users)) * RAND() + (SELECT MIN(id) FROM users) LIMIT 10

此方法效率比直接用SELECT * FROM users order by rand() LIMIT 10高很多

猜你喜欢

转载自blog.csdn.net/weixin_38399962/article/details/80105134