【连接查询】mySql多表连接查询与union与union all用法

时间:2022-09-20 14:34:06

1.准备两个表

表a:

  结构:

mysql> desc a;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(40) | NO   | PRI | NULL    |       |
| age   | int(11)     | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

 

  数据

【连接查询】mySql多表连接查询与union与union all用法

 

 

 

 

表b:

  结构

mysql> desc b;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| nameB | varchar(40) | YES  |     | NULL    |       |
| ageB  | int(11)     | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

  数据:

【连接查询】mySql多表连接查询与union与union all用法

 

 

 

 

 

 

2.进行连接查询测试:

(1)交叉连接(笛卡尔积)  cross join

mysql> select * from a,b;  #第一种 +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| A2   |    2 | B1    |    1 |
| A1   |    1 | B2    |   22 |
| A2   |    2 | B2    |   22 |
+------+------+-------+------+
4 rows in set (0.00 sec)

mysql> select * from a cross join b;  #第二种 +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| A2   |    2 | B1    |    1 |
| A1   |    1 | B2    |   22 |
| A2   |    2 | B2    |   22 |
+------+------+-------+------+
4 rows in set (0.00 sec)

mysql> select a.*,b.* from a cross join b;  #第二种的又一个写法 +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| A2   |    2 | B1    |    1 |
| A1   |    1 | B2    |   22 |
| A2   |    2 | B2    |   22 |
+------+------+-------+------+
4 rows in set (0.00 sec)

 

 

 

 

 (2)内连接    join 或 inner join(在笛卡尔积的基础上过滤)

 

  • 显示内连接

(1)不带条件的内连接

mysql> select a.*,b.* from a inner join b on a.age=b.ageb;  #第一种 inner join
+------+------+-------+------+ | name | age | nameB | ageB | +------+------+-------+------+ | A1 | 1 | B1 | 1 | +------+------+-------+------+ 1 row in set (0.00 sec)

 

 

mysql> select a.*,b.* from a join b on a.age=b.ageb;  #第二种 join (默认是inner join) +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
+------+------+-------+------+
1 row in set (0.00 sec)

 

 

三个表的显示内连接:

SELECT
  a.*,
  b.*,
  c.*
FROM exampaper a
  INNER JOIN bigquestion b
  INNER JOIN exampaperquestion c
    ON a.paperId = b.paperId
      AND b.bigQuertionId = c.bigQuertionId

 

四个表的显示内连接:

SELECT
    train.trainingSchemaName,
    train.majorName,
    train.createTime,
    tc.*, course.*, type.*
FROM
    trainschemeinfo train
JOIN train_course tc ON train.trainingSchemeID = tc.trainningSchemeID
INNER JOIN t_course_base_info course ON tc.courseID = course.courseId
INNER JOIN coursetypeinfo type ON tc.typeNum = type.typeNum
WHERE
    tc.trainningSchemeID = '661ecb064b164d1ea133956f89beddb7'

 

与之等价的隐士内连接:

SELECT
    train.trainingSchemaName,
    train.majorName,
    train.createTime,
    tc.*, course.*, type.*
FROM
    trainschemeinfo train,
    train_course tc,
    t_course_base_info course,
    coursetypeinfo type
WHERE
    train.trainingSchemeID = tc.trainningSchemeID
AND tc.courseID = course.courseId
AND tc.typeNum = type.typeNum
AND tc.trainningSchemeID = '661ecb064b164d1ea133956f89beddb7'

 

 

 

 

 

 (2)显示内连接带条件

mysql> select a.*,b.* from a join b on a.age=b.ageb having a.name='A1';  #having从查出的数据中挑选满足条件的元祖 +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
+------+------+-------+------+
1 row in set (0.00 sec)
  
mysql> select a.*,b.* from a join b on a.age=b.ageb where a.name='A1';  #where查询满足条件的元素 +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
+------+------+-------+------+
1 row in set (0.00 sec)

 

 

 

 

  • 隐士内连接:
mysql> select * from a,b where a.age=b.ageb;  
+------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
+------+------+-------+------+
1 row in set (0.00 sec)

mysql> select * from a,b where a.age=b.ageb and a.name='A1';
+------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
+------+------+-------+------+
1 row in set (0.00 sec)

mysql> select * from a,b where a.age=b.ageb having a.name='A1';
+------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
+------+------+-------+------+
1 row in set (0.00 sec)

 

  where是从本地磁盘查询满足条件的元素,having是从查出的数据中挑选满足条件的元素。执行权限   where>sum()..聚合函数>having

  

 

 

 (3)左外连接:(拿左边的匹配右边的,没有找到右边的为null)

mysql> select * from a left join b on a.age = b.ageb;  #第一种 left join +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| A2   |    2 | NULL  | NULL |
+------+------+-------+------+
2 rows in set (0.00 sec)

mysql> select * from a left outer join b on a.age = b.ageb;  #第二种 left outer join +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| A2   |    2 | NULL  | NULL |
+------+------+-------+------+
2 rows in set (0.00 sec)

 

 

 

(4)右外连接:(拿右边的匹配左边的,没有找到左边的为null)

mysql> select * from a right join b on a.age = b.ageb;  #第一种 right join +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| NULL | NULL | B2    |   22 |
+------+------+-------+------+
2 rows in set (0.00 sec)

mysql> select * from a right outer join b on a.age = b.ageb;  #第二种 right outer join +------+------+-------+------+
| name | age  | nameB | ageB |
+------+------+-------+------+
| A1   |    1 | B1    |    1 |
| NULL | NULL | B2    |   22 |
+------+------+-------+------+
2 rows in set (0.00 sec)

 

 

3.Union 和 union all  取两个表的并集测试

修改b表,加一条和a表重复的数据

b表数据:

【连接查询】mySql多表连接查询与union与union all用法

 

 

a表数据:

【连接查询】mySql多表连接查询与union与union all用法

 

 

 

(1)   union:   自动去掉重复元素

mysql> select * from a union select * from b;
+------+------+
| name | age  |
+------+------+
| A1   |    1 |
| A2   |    2 |
| B1   |    1 |
| B2   |   22 |
+------+------+
4 rows in set (0.00 sec)

 

 

 总结:

union:联合的意思,即把两次或多次查询结果合并起来。
要求:两次查询的列数必须一致
推荐:列的类型可以不一样,但推荐查询的每一列,想对应的类型以一样
可以来自多张表的数据:多次sql语句取出的列名可以不一致,此时以第一个sql语句的列名为准。
如果不同的语句中取出的行,有完全相同(这里表示的是每个列的值都相同),那么union会将相同的行合并,最终只保留一行。也可以这样理解,union会去掉重复的行。
如果不想去掉重复的行,可以使用union all。
如果子句中有order by,limit,需用括号()包起来。推荐放到所有子句之后,即对最终合并的结果来排序或筛选。

 

 

(2)    union all  保留重复元素

   UNION ALL 命令和 UNION 命令几乎是等效的,不过 UNION ALL 命令会列出所有的值。

mysql> select * from a union all select * from b;
+------+------+
| name | age  |
+------+------+
| A1   |    1 |
| A2   |    2 |
| B1   |    1 |
| B2   |   22 |
| A1   |    1 |
+------+------+
5 rows in set (0.00 sec)

 

  

 

 

 

总结:

  UNION 用于合并两个或多个 SELECT 语句的结果集,并消去表中任何重复行。
  UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型。
  同时,每条 SELECT 语句中的列的顺序必须相同.

  默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
  当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行

 注意:

1、UNION 结果集中的列名总是等于第一个 SELECT 语句中的列名
2、UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同