MySQL高级查询

为了便于说明下文中的例子,首先创建如下三张表:

mysql> SELECT * FROM student;
+----+------+-----+-----+
| id | name | age | sex |
+----+------+-----+-----+
|  1 | 张三 |  18 | 男  |
|  2 | 李四 |  20 | 女  |
+----+------+-----+-----+
2 rows in set (0.00 sec)

mysql> SELECT * FROM subject;
+------+---------+---------+------------------+
| id   | subject | teacher | description      |
+------+---------+---------+------------------+
| 1001 | 语文    | 王老师  | 本次考试比较简单 |
| 1002 | 数学    | 刘老师  | 本次考试比较难单 |
+------+---------+---------+------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM score;
+----+------------+------------+-------+
| id | student_id | subject_id | score |
+----+------------+------------+-------+
|  1 |          1 |       1001 |    80 |
|  2 |          2 |       1001 |    60 |
|  3 |          1 |       1002 |    70 |
|  4 |          2 |       1002 |  60.5 |
+----+------------+------------+-------+

子查询

子查询可以把一个查询嵌套在另一个查询当中的查询。

SELECT colunm FROM table1 WHERE condition

子查询一般分为内部查询和外部查询,内部查询即为condition语句,外部查询即上例中的SELECT colunm FROM table1 WHERE..

如查询score表中的语文成绩:

mysql> SELECT score FROM score WHERE subject_id = (
    -> SELECT id FROM subject WHERE subject='语文'
    -> );
+-------+
| score |
+-------+
|    80 |
|    60 |
+-------+

该例中SELECT score FROM score WHERE subject_id =..为外部查询,SELECT id FROM subject WHERE subject='语文'为内部查询。

子查询的结果均为外部查询的表,而不能包括内部查询的结果。对于上例,也就说是,我们查询到的结果,均为score中的内容,而不能获得subject表中的内容。

联结查询

子查询只能显示一张表的数据,但我们想要同时查询显示多张表的数据时,就可以使用联结查询。

内联结

又叫等值联结,基于两个表之间的相等测试。查询两个或多个表的交集
语法:

SELECT * FROM table1 AS t1 INNER JOIN table2 AS t2 ON t1.column = t2.column;
  • 例子
    同时显示学生姓名,科目和成绩
mysql> SELECT name , subject , score
    -> FROM score AS s
    -> INNER JOIN student AS stu ON s.student_id = stu.id
    -> INNER JOIN subject AS sub ON s.subject_id = sub.id;
+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三 | 语文    |    80 |
| 李四 | 语文    |    60 |
| 张三 | 数学    |    70 |
| 李四 | 数学    |  60.5 |
+------+---------+-------+

description列只存在于subject表中,不是三张表的交集。因此,当我们内联结三张表后是查询不到description的。

mysql> SELECT desctiption
    -> FROM score AS s
    -> INNER JOIN student AS stu ON s.student_id = stu.id
    -> INNER JOIN subject AS sub ON s.subject_id = sub.id;
ERROR 1054 (42S22): Unknown column 'desctiption' in 'field list'

外联结

以某张表为主,取出里面的所有记录, 然后每条与另外一张表进行连接: 不管能不能匹配上条件,最终都会保留: 能匹配,正确保留; 不能匹配,其他表的字段都置空NULL.

外联结分为左外联结和右外联结。左外联结即以左边的表为主表;右外联结即以右边的表为主表。所谓左右,即为代码中表的顺序,第一个为左,最后一个为右。

  • 例子

为了使外联结的示例更明显,删除student表中id=1的记录

mysql> DELETE FROM student WHERE id = 1;
Query OK, 1 row affected (0.20 sec)

mysql> SELECT * FROM student;
+----+------+-----+-----+
| id | name | age | sex |
+----+------+-----+-----+
|  2 | 李四 |  20 | 女  |
+----+------+-----+-----+

score为主表,左外联结subjectstudent

mysql> SELECT * FROM score AS s
    -> LEFT JOIN subject AS sub ON s.subject_id = sub.id
    -> LEFT JOIN student AS stu ON s.student_id = stu.id;
+----+------------+------------+-------+------+---------+---------+------------------+------+------+------+------+
| id | student_id | subject_id | score | id   | subject | teacher | description      | id   | name | age  | sex  |
+----+------------+------------+-------+------+---------+---------+------------------+------+------+------+------+
|  2 |          2 |       1001 |    60 | 1001 | 语文    | 王老师  | 本次考试比较简单 |    2 | 李四 |   20 | 女   |
|  4 |          2 |       1002 |  60.5 | 1002 | 数学    | 刘老师  | 本次考试比较难单 |    2 | 李四 |   20 | 女   |
|  1 |          1 |       1001 |    80 | 1001 | 语文    | 王老师  | 本次考试比较简单 | NULL | NULL | NULL | NULL |
|  3 |          1 |       1002 |    70 | 1002 | 数学    | 刘老师  | 本次考试比较难单 | NULL | NULL | NULL | NULL |
+----+------------+------------+-------+------+---------+---------+------------------+------+------+------+------+

注意到三四行的学生相关信息为NULL,因为该两行的student_id为1,student表中不存在该学生,因此查不到。

而如果以student表为主表,则查询的结果只有两条记录。这是因为student中只有id为2的学生,三张表中与该生有关的记录只有两条。

如下例,以student为主表,右外联结scoresubject

mysql> SELECT * FROM score AS s
    -> RIGHT JOIN subject AS sub ON s.subject_id = sub.id
    -> RIGHT JOIN student AS stu ON s.student_id = stu.id;
+------+------------+------------+-------+------+---------+---------+------------------+----+------+-----+-----+
| id   | student_id | subject_id | score | id   | subject | teacher | description      | id | name | age | sex |
+------+------------+------------+-------+------+---------+---------+------------------+----+------+-----+-----+
|    2 |          2 |       1001 |    60 | 1001 | 语文    | 王老师  | 本次考试比较简单 |  2 | 李四 |  20 | 女  |
|    4 |          2 |       1002 |  60.5 | 1002 | 数学    | 刘老师  | 本次考试比较难单 |  2 | 李四 |  20 | 女  |
+------+------------+------------+-------+------+---------+---------+------------------+----+------+-----+-----+

因此,外联结就是在主表的记录基础上,查询联结的表的并集。

组合查询

组合多个查询语句

  1. 对单个表执行多个查询,按照单个查询返回数据。

查询score表中分数大于70并且学生id 为1的记录:

mysql> SELECT * FROM score WHERE score > 70
    -> UNION
    -> SELECT * FROM score WHERE student_id = 1;
+----+------------+------------+-------+
| id | student_id | subject_id | score |
+----+------------+------------+-------+
|  1 |          1 |       1001 |    80 |
|  3 |          1 |       1002 |    70 |
+----+------------+------------+-------+

当然也可以使用AND写为一句:

mysql> SELECT * FROM score WHERE score > 70 AND student_id = 1;
+----+------------+------------+-------+
| id | student_id | subject_id | score |
+----+------------+------------+-------+
|  1 |          1 |       1001 |    80 |
+----+------------+------------+-------+
  • 在单个查询中,从不同表中返回类似结构的数据。
    比如,复制student表的结构创建表student_2,并添加一条记录:
mysql> CREATE TABLE student_2 LIKE student;
Query OK, 0 rows affected (0.96 sec)

mysql> INSERT INTO student_2 VALUES (3,'王五',17,'男');
Query OK, 1 row affected (0.10 sec)

组合查询

mysql> SELECT * FROM student
    -> UNION
    -> SELECT * FROM student_2;
+----+------+-----+-----+
| id | name | age | sex |
+----+------+-----+-----+
|  2 | 李四 |  20 | 女  |
|  3 | 王五 |  17 | 男  |
+----+------+-----+-----+

你可能感兴趣的:(MySQL高级查询)