连接探索(交叉连接,内连接,外连接)

创建临时表

select * into #t1 from (
select 0 num union all
select 1 num union all
select 2 num union all
select 3 num union all
select 4 num union all
select 5 num union all
select 6 num union all
select 7 num union all
select 8 num union all
select 9 num
) T;
select * into #t2 from (
select 0 num union all
select 1 num union all
select 2 num union all
select 3 num union all
select 4 num union all
select 5 num 
) T;

交叉连接,内连接,外连接探索

交叉连接 笛卡尔积
内连接 笛卡尔积+过滤
外连接 笛卡尔积+过滤+添加外部行(用NULL作占位符)

--CROSS JOIN
select * from #t1 a cross join #t2 b;--cartesian product
/*
0   0
1   0
2   0
3   0
4   0
5   0
6   0
7   0
8   0
9   0
0   1
1   1
2   1
3   1
4   1
5   1
6   1
7   1
8   1
9   1
0   2
1   2
2   2
3   2
4   2
5   2
6   2
7   2
8   2
9   2
0   3
1   3
2   3
3   3
4   3
5   3
6   3
7   3
8   3
9   3
0   4
1   4
2   4
3   4
4   4
5   4
6   4
7   4
8   4
9   4
0   5
1   5
2   5
3   5
4   5
5   5
6   5
7   5
8   5
9   5
*/

--JOIN
select a.num as anum ,b.num as bnum from #t1 a join #t2 b on a.num=b.num
/*
0   0
1   1
2   2
3   3
4   4
5   5
*/
--实现步骤拆解
select * from (
select  a.num as anum ,b.num as bnum from #t1 a cross join #t2 b --Step 1 :cartesian product
) T
where anum=bnum --Step2 :filter
;
/*
0   0
1   1
2   2
3   3
4   4
5   5
*/

--outer join
select a.num as anum ,b.num as bnum from #t1 a left outer join #t2 b on a.num=b.num
/*
0   0
1   1
2   2
3   3
4   4
5   5
6   NULL
7   NULL
8   NULL
9   NULL
*/
--实现步骤拆解
select * from (
select  a.num as anum ,b.num as bnum from #t1 a cross join #t2 b --Step 1 :cartesian product
) T
where anum=bnum --Step2 :filter
union all
-- Step3 : add outer column
select A.num anum, NULL bnum from #t1 A where a.num not in ( select anum from (
select  a.num as anum ,b.num as bnum from #t1 a cross join #t2 b --Step 1 :cartesian product
) T
where anum=bnum --Step2 :filter
);
/*
0   0
1   1
2   2
3   3
4   4
5   5
6   NULL
7   NULL
8   NULL
9   NULL
*/

OUTER JOIN中过滤条件失效的问题及解析

--下面外连接的结果以及生产逻辑
select * from #t1 a left join #t2 b on (a.num=b.num and b.num=1);
/*
0   NULL
1   1
2   NULL
3   NULL
4   NULL
5   NULL
6   NULL
7   NULL
8   NULL
9   NULL
*/
select * from #t1 a left join #t2 b on (a.num=b.num and a.num=1);
/*
0   NULL
1   1
2   NULL
3   NULL
4   NULL
5   NULL
6   NULL
7   NULL
8   NULL
9   NULL
*/
select * from #t1 a left join #t2 b on (a.num=b.num and a.num=1 and b.num=2);
/*
0   NULL
1   NULL
2   NULL
3   NULL
4   NULL
5   NULL
6   NULL
7   NULL
8   NULL
9   NULL
*/
select * from #t1 a left join #t2 b on (a.num=b.num and a.num=1 and b.num=1);
/*
0   NULL
1   1
2   NULL
3   NULL
4   NULL
5   NULL
6   NULL
7   NULL
8   NULL
9   NULL
*/
--因为需要添加外部行,所以#t1的过滤条件无法真正对#t1进行过滤,若要过滤需要在where条件里面再增加一层过滤

--原SQL
select * from #t1 a left join #t2 b on (a.num=b.num and a.num=1 and b.num=1);
--真正理解外连接逻辑之后不难理解,实现步骤拆解
select * from (
select  a.num as anum ,b.num as bnum from #t1 a cross join #t2 b --Step 1 :cartesian product
) T
where anum=bnum and anum=1 and bnum=1--Step2 :filter
union all
-- Step3 : add outer column
select A.num anum, NULL bnum from #t1 A where a.num not in ( select anum from (
select  a.num as anum ,b.num as bnum from #t1 a cross join #t2 b --Step 1 :cartesian product
) T
where anum=bnum and anum=1 and bnum=1--Step2 :filter
);

注意:外连接后面跟内连接或右外连接,都会抵消外连接的外部行(NULL被过滤掉)。

--外连接外部行被过滤问题
select * from #t1 a left join #t2 b on a.num=b.num join #t2 c on c.num=b.num
/*
0   0   0
1   1   1
2   2   2
3   3   3
4   4   4
5   5   5
*/
--原SQL,由于后一步join涉及到对b.num的过滤,而a添加的外部行的b表字段的占位符是NULL,会被过滤掉

--不过滤掉外部行的逻辑实现
select * from #t2 b join #t2 c on c.num=b.num right join #t1 a on a.num=b.num --way1
select * from #t1 a left join (#t2 b join #t2 c on c.num=b.num) on a.num=b.num --way2
/*
0   0   0
1   1   1
2   2   2
3   3   3
4   4   4
5   5   5
6   NULL    NULL
7   NULL    NULL
8   NULL    NULL
9   NULL    NULL
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值