MySQL连接查询,子查询,union(合并),分页

连接查询涉及到主键,外键知识,后面讲

建立两种简单的表作为例子: 

mysql> select * from student;
+----+------+-------+
| id | name | s_tid |
+----+------+-------+
|  1 | 小明 |     1 |
|  4 | 小李 |     1 |
|  5 | 小王 |     1 |
|  6 | 小小 |     2 |
+----+------+-------+
4 rows in set (0.02 sec)

mysql> select * from teacher;
+-----+--------+
| tid | tname  |
+-----+--------+
|   1 | 王老师 |
|   2 |  小小  |
+-----+--------+
2 rows in set (0.02 sec)

什么是连接查询?

从一张表中单独查询,称为单表查询。

连接查询:跨表查询,把两张或以上的表联合起来查询数据。 

连接查询的方式:

所有连接方式都会先生成临时笛卡尔积表,笛卡尔积是关系代数里的一个概念,表示两个表中的每一行数据任意组合。

连接查询的分类:

根据语法的年代分类:

        SQL92:1992年的时候出的语法(from 表,表)

        SQL99:1999年的时候出现的语法(join  on)

根据表连接的方式分类:

        内连接:

                等值连接

                非等值连接

                自连接

        外连接:

                左外连接(左连接)

                右外连接(右连接)

                全连接

 SQL92:

直接在from后面把要查询的表用逗号隔开写出来,

条件得用(表名.字段名)来比较,

        

一般用取别名的方式,这样效率更高。

        在from后面起别名,因为它是最开始执行的。

        没有起别名。 

mysql> select tname,name from teacher,student where teacher.tid=student.s_tid;
+--------+------+
| tname  | name |
+--------+------+
| 王老师 | 小明 |
| 王老师 | 小李 |
| 王老师 | 小王 |
|  小小  | 小小 |
+--------+------+
4 rows in set (0.00 sec)

        起别名(这样效率更高,减少了表的连接次数)

mysql> select t.tname,s.name from teacher t,student s where t.tid=s.s_tid;
+--------+------+
| tname  | name |
+--------+------+
| 王老师 | 小明 |
| 王老师 | 小李 |
| 王老师 | 小王 |
|  小小  | 小小 |
+--------+------+
4 rows in set (0.00 sec)

SQL99

使用join 来连接表,on来判断条件,

        下面是以内连接为例子,inner可以省略。(下面介绍内连接和外连接)

mysql> select t.tname,s.name from teacher t inner join student s on t.tid=s.s_tid;
+--------+------+
| tname  | name |
+--------+------+
| 王老师 | 小明 |
| 王老师 | 小李 |
| 王老师 | 小王 |
|  小小  | 小小 |
+--------+------+
4 rows in set (0.00 sec)

内连接

        等值连接:

inner join..on 字段=字段;

条件是等量关系的,inner可以省略。

mysql> select t.tname,s.name from teacher t inner join student s on t.tid=s.s_tid;
+--------+------+
| tname  | name |
+--------+------+
| 王老师 | 小明 |
| 王老师 | 小李 |
| 王老师 | 小王 |
|  小小  | 小小 |
+--------+------+
4 rows in set (0.00 sec)

        非等值连接:

条件不是等量关系的,inner可以省略。

mysql> select t.tname,s.name from student s join teacher t on s.id between 1 and 5;
+--------+------+
| tname  | name |
+--------+------+
|  小小  | 小明 |
| 王老师 | 小明 |
|  小小  | 小李 |
| 王老师 | 小李 |
|  小小  | 小王 |
| 王老师 | 小王 |
+--------+------+
6 rows in set (0.00 sec)

 自连接:

        自连接(self join)是SQL语句中经常要用的连接方式,使用自连接可以将自身表的一个镜像当作另一个表来对待,从而能够得到一些特殊的数据。

mysql> select a.name as "大名",b.name as"小名" from student a 
        join student b where a.id=b.s_tid;
+------+------+
| 大名 | 小名 |
+------+------+
| 小明 | 小明 |
| 小明 | 小李 |
| 小明 | 小王 |
+------+------+
3 rows in set (0.00 sec)

外连接:

左连接查询 left join

left join on / left outer join on,语法格式

       左外连接包含left join左表所有行,如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL).

mysql> select t.tname,s.name from student s left join teacher t on s.s_tid>t.tid;
+--------+------+
| tname  | name |
+--------+------+
| NULL   | 小明 |
| NULL   | 小李 |
| NULL   | 小王 |
| 王老师 | 小小 |
+--------+------+
4 rows in set (0.00 sec)

右连接查询right join

right join on / right outer join on,语法格式   

        右外连接包含right join右表所有行,如果左表中某行在右表没有匹配,则结果中对应左表的部分全部为空(NULL)。 

mysql> select t.tname,s.name from student s right join teacher t on s.s_tid>t.tid;
+--------+------+
| tname  | name |
+--------+------+
| 王老师 | 小小 |
|  小小  | NULL |
+--------+------+
2 rows in set (0.01 sec)

完全外连接(mysql中没有该语法,了解该概念就行)

        完全外连接包含左右两表中所有的行,如果右表中某行在左表中没有匹配,则结果中对应行右表的部分全部为空(NULL),如果左表中某行在右表中没有匹配,则结果中对应行左表的部分全部为空(NULL)。

子查询:

        什么是子查询?

select 语句中嵌套select语句,被嵌套的select语句被称为子查询。

        子查询可以出现在哪里? 

select 

..(select )

from

..(select )   在from后面,可以把查询结果看出一张新的表

where

..(select )

注意:

对应select后面的子查询来说,这个子查询只能返回一条结果,多于一条报错。

     select后面(了解)

 对应select后面的子查询,多于一条报错。

mysql> select (select id from student) as sname from student;
ERROR 1242 (21000): Subquery returns more than 1 row
mysql> select name,(select id from student where id=1) as sname from student;
+------+-------+
| name | sname |
+------+-------+
| 小明 |     1 |
| 小李 |     1 |
| 小王 |     1 |
| 小小 |     1 |
+------+-------+
4 rows in set (0.00 sec)

在from后面(掌握)

在from后面的子查询需要起一个别名,要不然会出现以下错误:

mysql> SELECT id,name from (select * from student where id>1);
ERROR 1248 (42000): Every derived table must have its own alias
mysql> SELECT id,name from (select * from student where id>1)as stu;
+----+------+
| id | name |
+----+------+
|  4 | 小李 |
|  5 | 小王 |
|  6 | 小小 |
+----+------+
3 rows in set (0.00 sec)

在where后面:

同样如果使用运算符连接,子查询的结果只能是一个,不然会报以下错误

mysql>  select id,name from student  where s_tid=(select tid from teacher);
ERROR 1242 (21000): Subquery returns more than 1 row
mysql>  select id,name from student  where s_tid=(select tid from teacher where tname=" 小小");
+----+------+
| id | name |
+----+------+
|  6 | 小小 |
+----+------+
1 row in set (0.00 sec)

union(合并查询结果集)

 union的效率更高一些,对于表连接来说,每连接一次新表,则匹配的次数满足笛卡儿积,成倍的翻。

但是union可以减少匹配的次数。在减少匹配的次数的情况下,还能完成两个结果集的拼接

        

使用union时必须注意,查询的结果必须保证列的数目相同。

如果是oracle还会要求类型也是一样,MySQL不做要求。

mysql>  select id,name from student
    -> union
    -> select tid,tname from teacher;
+----+--------+
| id | name   |
+----+--------+
|  1 | 小明   |
|  4 | 小李   |
|  5 | 小王   |
|  6 | 小小   |
|  1 | 王老师 |
|  2 |  小小  |
+----+--------+
6 rows in set (0.00 sec)

limit(分页)

limit作用:将查询结果集的一部分取出来。通常使用在分页查询当作。

        

分页的作用是为了提高用户的体验,因为一次全部都查出来,用户体验差,可以一页一页翻页看。

limit用法:

完整用法:

        limit  startIndex,length

                startIndex是起始下标,length是长度。

                起始下标从0开始。

缺省用法:limit 5;这是取前五。

注意:在MySQL当中Limit在order by排序 之后执行。

实例表:

mysql> select * from city;
+----+----------+-----------+-------+
| id | name     | parent_id | level |
+----+----------+-----------+-------+
|  1 | 安徽     |         0 |     1 |
|  2 | 江苏     |         0 |     1 |
|  3 | 合肥     |         1 |     2 |
|  4 | 合肥一区 |         3 |     3 |
|  5 | 扬州     |         2 |     2 |
|  6 | 南京     |         2 |     2 |
|  7 | 扬州一区 |         5 |     3 |
|  8 | 扬州二区 |         5 |     3 |
|  9 | 南京一区 |         6 |     3 |
| 10 | 南京二区 |         6 |     3 |
+----+----------+-----------+-------+
10 rows in set (0.00 sec)

 缺省用法:

mysql> select * from city limit 5;
+----+----------+-----------+-------+
| id | name     | parent_id | level |
+----+----------+-----------+-------+
|  1 | 安徽     |         0 |     1 |
|  2 | 江苏     |         0 |     1 |
|  3 | 合肥     |         1 |     2 |
|  4 | 合肥一区 |         3 |     3 |
|  5 | 扬州     |         2 |     2 |
+----+----------+-----------+-------+
5 rows in set (0.00 sec)

完整用法: 

     limit  startIndex,length使用时不需要 加括号

mysql> select * from city limit 0,5;
+----+----------+-----------+-------+
| id | name     | parent_id | level |
+----+----------+-----------+-------+
|  1 | 安徽     |         0 |     1 |
|  2 | 江苏     |         0 |     1 |
|  3 | 合肥     |         1 |     2 |
|  4 | 合肥一区 |         3 |     3 |
|  5 | 扬州     |         2 |     2 |
+----+----------+-----------+-------+
5 rows in set (0.00 sec)

DQL语句总结:

select 

        ...

from

        ...

group by

        ...

having

        ...

order by

        ...

limit

        ...

执行顺序:1,from        2.where        3,group by        4,having

                  5,select        6,order by        7,limit...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值