准备测试数据
create table class(
cid int(10),
cdesc varchar(20)
);
create table student(
sid int(10),
name varchar(20),
age int(3),
cid int(10)
);
create table teacher(
tid int(10),
name varchar(20),
cid int(10)
);
insert into class values(1, "PHP"),(2, "Java"),(3, "C++"),(4,"SQL");
insert into student values(1, "s1",16,1),(2, "s2",17,2),(3, "s3",18,3),(4,"s4",19,4),(5, "s5",18,3),(6,"s6",19,4);
insert into teacher values(1, "t1",1),(2, "t2",2),(3, "t3",3),(4,"t4",4);
alter table student add constraint sid_pk primary key(sid);
连接查询 join
连接查询方式有:内连接、外连接(常用,分为左连接和右连接)、自然连接、交叉连接。借助连接查询,可以同时查看多张表中的数据。
- 内连接:有条件连接,用 on 在多个表之间指定条件连接。如果两个表的任一个匹配不到数据,则返回空
- 外连接:有条件连接,用 on 在多个表之间指定条件连接。只要主表(左连接的左表,右连接的右表)匹配到数据,就不会返回空,未匹配到数据的字段填充 NULL
mysql> select * from class join student on student.cid = class.cid where class.cid = 1;
Empty set (0.00 sec)
mysql> select * from class left join student on student.cid = class.cid where class.cid = 1;
+-----+-------+------+------+------+------+
| cid | cdesc | sid | name | age | cid |
+-----+-------+------+------+------+------+
| 1 | PHP | NULL | NULL | NULL | NULL |
+-----+-------+------+------+------+------+
1 row in set (0.00 sec)
mysql> select * from student left join class on student.cid = class.cid where class.cid = 1;
Empty set (0.00 sec)
语法
- 内连接:select 字段列表 from 左表 [inner] join 右表 on 左表.字段 = 右表.字段;
- 外连接(重要):
左外连接:select 字段列表 from 左表 left join 右表 on 左表.字段 = 右表.字段;
右外连接:select 字段列表 from 左表 right join 右表 on 左表.字段 = 右表.字段; - 自然连接:有条件连接,但是不需要指定,MySQL 自动依据“同名字段”连接(多个同名字段就都作为条件)。
- 交叉连接 cross join:无条件连接,取笛卡尔积,返回的记录数等于各表记录数的乘积。
联合查询 union
将多个查询结果进行拼接,多个查询结果的字段数必须相同,类型可以不同。支持两个选项:
- all:不对相同结果去重,默认选项
- distinct:去重
mysql> select age from student union distinct select cdesc from class;
+------+
| age |
+------+
| 17 |
| 18 |
| 19 |
| C++ |
| Java |
| PHP |
| SQL |
+------+
7 rows in set (0.00 sec)
子查询
- from 子查询:from 后面是子查询。注意这个子查询会创建临时表,需要为其起个别名:
mysql> select sid from (select * from student where sid > 2);
ERROR 1248 (42000): Every derived table must have its own alias
mysql> select sid from (select * from student where sid > 2) as s;
+-----+
| sid |
+-----+
| 3 |
| 4 |
| 5 |
| 6 |
+-----+
4 rows in set (0.00 sec)
- where 子查询:where 后面是子查询。
mysql> select * from student where age > (select age from student where sid = 3);
+-----+------+------+------+
| sid | name | age | cid |
+-----+------+------+------+
| 4 | s4 | 19 | 4 |
| 6 | s6 | 19 | 4 |
+-----+------+------+------+
2 rows in set (0.00 sec)
- where exists 子查询:where exists 后面是子查询。
mysql> select * from class where exists(select * from student where cid=1);
Empty set (0.00 sec)
mysql> select * from class where exists(select * from student where cid=2);
+-----+-------+
| cid | cdesc |
+-----+-------+
| 1 | PHP |
| 2 | Java |
| 3 | C++ |
| 4 | SQL |
+-----+-------+
4 rows in set (0.00 sec)