[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 | +------+-------+---------+-------+------------+