FOR each row lt in LT {// 遍历左表的每一行BOOL b =FALSE;FOR each row rt in RT such that P1(lt, rt) {// 遍历右表每一行,找到满足on条件的行IF P2(lt, rt) {//满足 where 过滤条件
t:=lt||rt;//合并行,输出该行
}
b=TRUE;// lt在RT中有对应的行
}
IF(!b) { // 遍历完RT,发现lt在RT中没有有对应的行,则尝试用null补一行IF P2(lt,NULL) {// 补上null后满足 where 过滤条件
t:=lt||NULL;// 输出lt和null补上的行
}
}
}
2. 例子:
那么现在有两个需求:
找出每个班级的名称及其对应的女同学数量
找出一班的同学总数
对于需求1,大多数人不假思索就能想出如下两种sql写法
正确的:
SELECT c.name,count(s.name)as num
FROM classes c leftjoin students s
on s.class_id = c.id
and s.gender ='F'groupby c.name
-- 错误的SELECT c.name,count(s.name)as num
FROM classes c leftjoin students s
on s.class_id = c.id
where s.gender ='F'groupby c.name
3.总结
A left B join on A.id =B.id and A.name=’ ’ and B.name=’ ’ 等条件:不管怎样都会保留左表的所有列。 只保留B表中符合关联条件的。
A left B join on A.id =B.id and A.name=’ ’ and B.name=’ ’ where A.age=‘xxx’ 等价于在A表中先where 后再关联left join,因为left join 后无论如何都会保留A表中全部的内容,再使用where 对A表过滤 相当于提前过滤 再关联 结果一样。
(select*from A where A.age='xxx') A left B joinon A.id =B.id and A.name=' 'and B.name=' '
A left B join on A.id =B.id and A.name='TTTT ’ and B.name='XXXX ’ where B.age=‘xxx’ 等价于 A join B 因为A left join B 将B中没有join上的就为空 此时你对B进行过滤 相等于把B为空的都去掉 就只剩下 A和B都能join上的。 所以相当于 inner join