[mysql基础文档]-30-左右内联查询

引言

左右连接查询和内联查询的工作方式很类似,所不同的是,左右连接查询会将左值或右值作为基准值进行对比。

文章目录

0×1.如何使用left join和right join查询

使用上一篇文章inner join查询实例中所创建的表A和B来演示左右联合查询,建表语法请参考上一篇文章,这里仅给出表结构:

					mysql> select * from A;
					+-----+-------+
					| aid | aname |
					+-----+-------+
					|   1 | susam |
					|   2 | jenny |
					|   3 | mary  |
					+-----+-------+

					mysql> select * from B;
					+-----+--------+
					| bid | bname  |
					+-----+--------+
					|   2 | tom    |
					|   3 | john   |
					|   4 | george |
					+-----+--------+

					--左联接查询,在这个实例中A表是"A left join B"这个表达式的左值,作为参照表使用A表aid列连接B表bid列,在这个过程中,将列出所有A表下面每个aid字段所对应的记录,当B表对应的bid中没有字段匹配的时候,用NULL填充,有人可能会问,为什么没有4,因为用左值作为参考,aid中没有4
					mysql> select * from A left join B on A.aid=B.bid;
					+-----+-------+------+-------+
					| aid | aname | bid  | bname |
					+-----+-------+------+-------+
					|   1 | susam | NULL | NULL  |
					|   2 | jenny |    2 | tom   |
					|   3 | mary  |    3 | john  |
					+-----+-------+------+-------+

					--右连接查询同理,顾名思义,B是"A right join B"这个表达式的右值,所以用B作为参考表,A中不存在的对应记录用NULL填充
					mysql> select * from A right join B on A.aid=B.bid;
					+------+-------+-----+--------+
					| aid  | aname | bid | bname  |
					+------+-------+-----+--------+
					|    2 | jenny |   2 | tom    |
					|    3 | mary  |   3 | john   |
					| NULL | NULL  |   4 | george |
					+------+-------+-----+--------+
					

0×2.联合查询综合经典实例

实例1,创建一个联合查询,将"[mysql基础文档]-24-select查询基础"第一部分所创建的cellphone表,请参考:[cellphone数据表],以及"[mysql基础文档]-28-子查询"第二部分中创建的category表,请参考:[category数据表],cellphone表中的goods_name,category表中的cat_id,cat_name,这三列查询并显示成一个结果集

					--使用内联查询,将category的cat_id列同cellphone的cat_id列连接起来,
					mysql> select category.cat_id,category.cat_name,cellphone.goods_name
					    -> from
					    -> cellphone inner join category
					    -> on
					    -> category.cat_id=cellphone.cat_id;
					+--------+----------+--------------+
					| cat_id | cat_name | goods_name   |
					+--------+----------+--------------+
					|      1 | XiaoMi   | hongMI2a     |
					|      1 | XiaoMi   | MInote       |
					|      1 | XiaoMi   | hongMI2      |
					|      1 | XiaoMi   | MI4          |
					|      2 | Samsung  | GalaxyN9200  |
					|      3 | Apple    | iPhone6A1586 |
					|      4 | Meizu    | MeizuNote2   |
					|      5 | Huawei   | Huawei4X     |
					|      2 | Samsung  | GalaxyG9250  |
					|      5 | Huawei   | Huawei4A     |
					|      4 | Meizu    | MX5          |
					|      3 | Apple    | iPhone5s     |
					|      2 | Samsung  | GalaxyN9109W |
					|      4 | Meizu    | MX4          |
					|      3 | Apple    | iPhone4s     |
					|      5 | Huawei   | Huawei6      |
					|      3 | Apple    | iPhone6s     |
					|      4 | Meizu    | MX4Pro       |
					|      2 | Samsung  | GalaxyS6     |
					|      5 | Huawei   | Huawei7      |
					+--------+----------+--------------+

					--有兴趣的朋友可以试着显示这张完整的内联表
					mysql> select * from cellphone inner join category on category.cat_id=cellphone.cat_id;

					--如果仅需要筛选出cat_id为3的完整记录,可以如下,这里要注意,当内联后的表中包含同名列时,使用时需要指定表前缀(category.cat_id)
					mysql> select *
					    -> from
					    -> cellphone inner join category
					    -> on
					    -> category.cat_id=cellphone.cat_id
					    -> where
					    -> category.cat_id=3;
					

实例2,一道真实的内联查询面试题

现有两张表如下:

					mysql> create table team(tid tinyint,tname char(3));
					mysql> insert into team values
					    -> (1,'T1'),
					    -> (2,'T2'),
					    -> (3,'T3');

					mysql> create table mat(cid tinyint unsigned,h tinyint,g tinyint,scoring char(10),sdate date);
					mysql> insert into mat values
					    -> (1,1,2,'2:0','2015-05-12'),
					    -> (2,2,3,'1:2','2015-06-01'),
					    -> (3,3,1,'2:5','2015-06-15'),
					    -> (4,2,1,'3:2','2015-07-15');

					--球队id和球队名称表team
					mysql> select * from team;
					+------+-------+
					| tid  | tname |
					+------+-------+
					|    1 | T1    |
					|    2 | T2    |
					|    3 | T3    |
					+------+-------+

					--球队比赛日期表,cid总比赛场数列,h表示主场,g表示客场,主客场列的值分别对应了team表的tid值,scoring是单场比赛得分,sdate是比赛日期
					mysql> select * from mat;
					+------+------+------+---------+------------+
					| cid  | h    | g    | scoring | sdate      |
					+------+------+------+---------+------------+
					|    1 |    1 |    2 | 2:0     | 2015-05-12 |
					|    2 |    2 |    3 | 1:2     | 2015-06-01 |
					|    3 |    3 |    1 | 2:5     | 2015-06-15 |
					|    4 |    2 |    1 | 3:2     | 2015-07-15 |
					+------+------+------+---------+------------+
					

要求,查询出"2015-06-01"至"2015-07-01"之间所有比赛记录,返回结果集格式要求"T1 2:0 T2 2015-06-01"。

					--还记得以前的分步思想吗?先用mat表的h列对应team表的tid列进行一次内联查询,使用as将第一个连接的team表命名为t1,t1中的tname顺序对应了主场的h值
					mysql> select *
					    -> from
					    -> mat inner join team as t1
					    -> on
					    -> mat.h=t1.tid;
					+------+------+------+---------+------------+------+-------+
					| cid  | h    | g    | scoring | sdate      | tid  | tname |
					+------+------+------+---------+------------+------+-------+
					|    1 |    1 |    2 | 2:0     | 2015-05-12 |    1 | T1    |
					|    2 |    2 |    3 | 1:2     | 2015-06-01 |    2 | T2    |
					|    3 |    3 |    1 | 2:5     | 2015-06-15 |    3 | T3    |
					|    4 |    2 |    1 | 3:2     | 2015-07-15 |    2 | T2    |
					+------+------+------+---------+------------+------+-------+

					--对上面的步骤再加工,将上面这一步的结果集作为一张完整的表,再次和team表进行内联查询,使用team的tid对应mat表的g列,从而可以得到客场作战的tname顺序,将第二个连接的team表命名为t2,虽然结果中有四列相同的tid和tname,但是大家要明白前面两列是t1表的,后面两列是t2表的,select筛选的时候会用到
					mysql> select *
					    -> from
					    -> mat inner join team as t1
					    -> on
					    -> mat.h=t1.tid
					    -> inner join team as t2
					    -> on
					    -> mat.g=t2.tid;
					+-----+---+---+---------+------------+------+-------+------+-------+
					| cid | h | g | scoring | sdate      | tid  | tname | tid  | tname |
					+-----+---+---+---------+------------+------+-------+------+-------+
					|   1 | 1 | 2 | 2:0     | 2015-05-12 |    1 | T1    |    2 | T2    |
					|   2 | 2 | 3 | 1:2     | 2015-06-01 |    2 | T2    |    3 | T3    |
					|   3 | 3 | 1 | 2:5     | 2015-06-15 |    3 | T3    |    1 | T1    |
					|   4 | 2 | 1 | 3:2     | 2015-07-15 |    2 | T2    |    1 | T1    |
					+-----+-------+---------+------------+------+-------+------+-------+

					--总表出来后,最后一次加工,按照题目要求的格式,写出select后面的部分代替星号,筛选出对应列和时间范围即可,cid列可写可不写
					mysql> select cid,t1.tname as hname,scoring,t2.tname as gname,sdate
					    -> from
					    -> mat inner join team as t1
					    -> on
					    -> mat.h=t1.tid
					    -> inner join team as t2
					    -> on
					    -> mat.g=t2.tid
					    -> where between '2015-06-01' and '2015-07-01';
					+------+-------+---------+-------+------------+
					| cid  | tname | scoring | gname | sdate      |
					+------+-------+---------+-------+------------+
					|    2 | T2    | 1:2     | T3    | 2015-06-01 |
					|    3 | T3    | 2:5     | T1    | 2015-06-15 |
					+------+-------+---------+-------+------------+