其实就是联结查询,那和之前的where+=的方式有什么不同嘛?
我们先来看看它怎么写的:
select name,score from student inner join score on student.id=score.stuid它的效果和之前的:
select name,score from student,score where student.id=score.stuid其实是一样的,只不过前者是显性的,后者是隐性的。但是,隐性连接随着数据库语言的规范和发展,已经逐渐被淘汰,比较新的数据库语言基本上已经抛弃了隐性连接,全部采用显性连接了。
一般要使得数据库查询语句性能好点遵循一下原则:
在做表与表的连接查询时,大表在前,小表在后不使用表别名,通过字段前缀区分不同表中的字段查询条件中的限制条件要写在表连接条件前尽量使用索引的字段做为查询条件尽量使用join而不是where来列出关联条件,特别是多个表联合的时候。
原因是:
在效率上,Where可能具有和Inner join一样的效率。但基本可以肯定的是Join的效率不比Where差。
使用join可以帮助检查语句中的无效或者误写的关联条件
多几个就多写几行呗
select name,score from student inner join score on student.id=score.stuid inner join ... on ... inner join ... on ... ...以左表为主(基准)表,不满足连接条件的也不过滤,为null就好了
select name,score from student left join score on student.id=score.stuid就拿上面的例子来说,student是左表,为学生表;score是右表,为成绩表
要是我不仅想查成绩,还想查谁没来考试呢?这时候就需要左外连接了(查询出来的结果null在最后)
同上,相反即可
结果是获取笛卡儿积
mysql> select * from canteen,score; +----+----------+------+------+---------+---------+------+ | id | money | tid | id | chinese | english | math | +----+----------+------+------+---------+---------+------+ | 1 | 100.0000 | 1 | 1 | 98 | 99 | 100 | | 1 | 100.0000 | 1 | 2 | 90 | 92 | 80 | +----+----------+------+------+---------+---------+------+ 2 rows in set (0.00 sec) mysql> select * from canteen cross join score; +----+----------+------+------+---------+---------+------+ | id | money | tid | id | chinese | english | math | +----+----------+------+------+---------+---------+------+ | 1 | 100.0000 | 1 | 1 | 98 | 99 | 100 | | 1 | 100.0000 | 1 | 2 | 90 | 92 | 80 | +----+----------+------+------+---------+---------+------+ 2 rows in set (0.00 sec)这两种写法是一样的
也就是去重的等值连接,咱们类比一下:
mysql> select * from canteen natural join score; +----+----------+------+---------+---------+------+ | id | money | tid | chinese | english | math | +----+----------+------+---------+---------+------+ | 1 | 100.0000 | 1 | 98 | 99 | 100 | +----+----------+------+---------+---------+------+ 1 row in set (0.00 sec) mysql> select * from canteen inner join score on canteen.id = score.id; +----+----------+------+------+---------+---------+------+ | id | money | tid | id | chinese | english | math | +----+----------+------+------+---------+---------+------+ | 1 | 100.0000 | 1 | 1 | 98 | 99 | 100 | +----+----------+------+------+---------+---------+------+ 1 row in set (0.00 sec)怎么破除呢?(假设t1、t2字段相同)
select * from t1 inner join t2 on using(id);但是不推荐,会出现这种情况,说明设计不合理了;尽量不用自然连接,用inner join写全来;因为你不知道表结构时,自然连接会出事
其实就是嵌套查询,毕竟数据库是面向集合的,可以拿着结果集继续查,举个例子:
select * from student where id in (select stuid from score where score>=85); 首先后半句查出来成绩不低于85的学生的学生id集合看student表里有没有满足条件(id在上面查出来的集合里,是or的关系)的实体关键就在in,判断前面的字段是否在后面查出来的集合中(你不必知道后面查出来的集合有什么,这一过程被隐藏了)
相反的,还有not in
这个和in容易搞混,要注意,exists表示的是子查询出来的集合里有没有东西,有东西就执行前面的语句,没有就不执行
select * from canteen where exists (select id from score where chinese>95);只要存在语文成绩大于95的,就查整张餐厅表,这是个存在问题;而in是需要满足条件的
一样,也有相反的not exists