首页 > 试题广场 >

Mysql(版本8.0.25)中表student_table

[单选题]
Mysql(版本8.0.25)中表student_table(id,name,birth,sex),插入如下记录:
('1004' , '张三' ,'2000-08-06' , '男');
('1009' , '李四', '2000-01-01', '男');
('1010' , '李四', '2001-01-01', '男');
('1006' , '王五', '2000-08-06' , '女');
('1008' , '张三', '2002-12-01', '女');
('1012' , '张三', '2001-12-01', '女');
('1011' , '李四', '2002-08-06' , '女');
('1013' , '赵六' ,'2000-09-06' , '男');
现有SQL:
select t1.*,t2.*
from (
select * from student_table where sex = '男' ) t1 
full join 
(select * from student_table where sex = '女')t2 
on  t1.name = t2.name ; 
如下SQL中与上述SQL实现的语义和结果一致的是()?
  • select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    left join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name
    union all
    select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    right join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name
    and t1.name is null ;
  • select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    left join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name
    union all
    select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    right join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name
    where t1.name is null ;
  • select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    left join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name
    and t1.name is null
    union all
    select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    right join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name ;
  • select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    left join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name
    where t1.name is null
    union all
    select t1.*,t2.*
    from (
    select * from student_table where sex = '男' ) t1
    right join
    (select * from student_table where sex = '女')t2
    on t1.name = t2.name ;
FULL JOIN 关键字会从左表和右表那里返回所有的行。如果 "t1" 中的行在表 "t2" 中没有匹配,或者如果 "t2" 中的行在表 "t1" 中没有匹配,这些行同样会列出。
  等价于 左连接后 再并上  左边为空 右表有值的那些记录。
  或者     左连接并上右连接的值 然后去除重复的记录  即 union 
发表于 2022-01-13 23:42:21 回复(0)
不是说mysql中不支持full jion吗,为什么这语句能实现啊
发表于 2022-03-31 10:08:11 回复(7)


因为FULL JOIN是所有的记录相当于t1和t2的合集,如下图所示

所以如果我们如果要通过RIGHT AND LEFT来达到FULL JOIN的效果,首先来看两个左右连接会产生的结果。
Left join
('1004' , '张三1' ,'2000-08-06' , '男');张三1

('1004' , '张三1' ,'2000-08-06' , '男')张三2
('1009' , '李四1', '2000-01-01', '男');李四1
('1010' , '李四2', '2001-01-01', '男')李四1

('1013' , '赵六' ,'2000-09-06' , '男');Null

Right join
Null('1006' , '王五', '2000-08-06' , '女');
张三1('1008' , '张三1', '2002-12-01', '女');

张三1('1012' , '张三2', '2001-12-01', '女');
李四1('1011' , '李四1', '2002-08-06' , '女');

李四2('1011' , '李四1', '2002-08-06' , '女');

利用合集思想来思考,在LEFT JOIN我们的合集是这样的

如果要补成全集,因为UNION ALL没有去除重复功能,所以中间交集部分是不能在RIGHT JOIN部分保留的,我们只需要补上上面空白的地方。
那么空白的地方要怎么补充呢?在使用RIGHT JOIN 后使用WHERE t1 IS NULL来补充。因为非空部分已经在LEFT JOIN 重复过了,所以t1 NULL的部分就是空白部分。(这个逻辑可以记下来)。如果还不够直观,可以再参考上面的结果。
针对A来记录以下思路A.错误
因为是使用右连接一开始会显示上方结果,但如果使用and,因为右连接保留女生的信息,那么会保留所有女生匹配为NULL的结果;
Null('1006' , '王五', '2000-08-06' , '女');
Null('1008' , '张三1', '2002-12-01', '女');
Null('1012' , '张三2', '2001-12-01', '女');
Null('1011' , '李四1', '2002-08-06' , '女');

用WHERE 则会保留原本右连接结果的第一行即Null('1006' , '王五', '2000-08-06' , '女');

编辑于 2023-01-27 04:14:36 回复(1)
为啥要有where t1.name is null
发表于 2022-02-06 20:22:44 回复(5)
and 和 where 
and是在表上,where是在结果总体上。
a选项中 右连接之后 and t1.name is null ; 结果是
null null null null  1006    王五    2000-08-06    
null null null null  1008    张三    2002-12-01    
null null null null  1012    张三    2001-12-01    
null null null null  1011    李四    2002-08-06    
相当于右侧表连接 左侧 而左侧数据为null要求下 只会列出右侧表所有列 之后左侧值null的组合
发表于 2022-03-03 15:17:48 回复(2)

解析:

考察点1、sql执行顺序:from >> on >> join >> where >> group by >> having >> select >> distinct >> unoin >> order by >> limit

考察点2、mysql不支持全外连接,因此可以使用left join 和 right join配合union实现

考察点3、on和where的区别:

  • on执行时机在表连接时根据嵌套循环算法SNJL(mysql仅支持该连接策略,有优化版本INJL:使用索引优化内层循环效率、BNJL:利用join buffer减少内层循环次数)针对驱动表(数据量较小的,left join一般为左表)的每一条记录,遍历关联表的每一项,将满足连接条件的放入结果集。

  • where是针对结果集作条件筛选。

A、union后的子表,on条件t1.name = t2.name and t1.name is null,显然没有满足的记录,但是连接类型为right join,因此保留t2全部记录,t1字段为null

该结果与左外连接的结果作并集,显然不是全外连接的结果,错误。C同理。

B正确,union all的第一个子表:左外连接的结果为满足连接的记录和左表中不满足连接条件的记录,第二个子表:通过where将右外连接中不满足连接条件的记录筛出,两者并集即为全外连接;

D、where t2.name is null才正确

个人理解,如有偏颇,欢迎指出
发表于 2022-10-02 16:22:14 回复(0)
a,b选项不一样吗?

发表于 2022-01-23 15:32:18 回复(2)
补充一下B输出

对方使用了【眩晕】!效果显著!
编辑于 2023-03-24 22:35:20 回复(0)
不是说mysql中不支持full jion吗,为什么这语句能实现啊

发表于 2022-09-11 17:57:39 回复(0)
union all没有去重 所以union all要手动去重
实际上重复的部分就是两个表name相同的记录;因为两个表的条件都是t1.name = t2.name
A最后的 and t1.name is null ;没有删除重复的部分 and是保留t1表为空的部分 因为第二个select是右连接 我们要的只有不重复的部分 右连接与第一个左连接的不重复部分就是仅保留右侧t2表的情况即t1表为空t2表有内容的情况就是t1.name is null的情况 所以利用where语句仅保留这种情况再做union all连接就能做到去重连接了 如果对于第一个表做处理应该筛选出右侧表为空的情况 即where t2.name = null
发表于 2022-07-28 16:37:30 回复(1)
好烦 没注意 where and
发表于 2022-05-27 15:56:03 回复(1)
话不多说,看图解题,画几个圈就知道答案了
编辑于 2024-03-21 00:13:03 回复(0)
这道题的答案有误,C选项的结果和答案说的不一样,而且题目中的选项没有加 全(),from后面有‘(’而没有‘)’
编辑于 2023-03-31 21:00:34 回复(0)
left与right union之后的结果应该就是参考答案里的A选项的前五行和D选项,在这样的结果进行where t1.name=NULL,那结果不就是只有一条吗?所以full join最后的结果该是什么?
发表于 2023-01-12 23:30:32 回复(1)
full join 是left join和right join的结合体
发表于 2022-10-17 14:30:28 回复(0)
要瞎了,A和B哪里不一样啊
发表于 2022-09-27 19:50:53 回复(0)
B
发表于 2022-09-01 10:43:14 回复(0)
本题题意全连接=A+A和B除了交集的部分,C项的错误在于,使用on筛选空值
发表于 2022-05-06 15:11:04 回复(0)
and 和Where 有啥区别?
发表于 2022-02-04 20:40:06 回复(1)
有没有朋友解释一下?
发表于 2021-12-25 15:55:03 回复(2)