假设现在有表t1, t2, t3,t1通过id左关联t2, t2通过id左关联t3, 要统计t3中关联t1(8, 9, 10, 11, 722, 723, 724)数量?
两种写法:
SQL1:
select
t1.id,
count(t3.id) as totalQuestionCnt
from eas_label t1
left join eas_question_label t2 on t1.id = t2.label_id and t2.del_flag = 0
left join eas_question t3 on t2.question_id = t3.id and t3.del_flag = 0
where t1.id in (
8, 9, 10, 11, 722, 723, 724
)
and t1.del_flag = 0
group by t1.id;
输出:
SQL2:
select
t1.id,
count(t3.id) as totalQuestionCnt
from eas_label t1
left join eas_question_label t2 on t1.id = t2.label_id
left join eas_question t3 on t2.question_id = t3.id
where t1.id in (
8, 9, 10, 11, 722, 723, 724
)
and t1.del_flag = 0
and t2.del_flag = 0
and t3.del_flag = 0
group by t1.id;
输出:
区别:
比较两种sql,发现数据都相同,唯一的区别在于,如果t1在t2或t3中没有关联数据,那么第一种写法会保留t1的所有数据,id为8, 9, 10, 11, 722, 723, 724的t1记录都在,没有关联数据,则totalQuestionCnt都为0;
而第二种写法是直接去除没有关联记录的t1数据,只保留在t2和t3中有关联数据的记录,即只有id为8和9的t1数据。
原因:
两种返回结果的差异原因,在于where条件在时生成临时表时过滤数据,这个临时表就是t1和t2和t3的关联表,就是在关联后,进行过滤;
而on条件是在生成临时表之前过滤数,就是说先过滤t2,t3,然后再跟t1关联,这时候,t1的所有数据都会保留。
总结:
两种写法都对,只是要看场景,具体看需求是,是否当没有关联数据时,left join 左表的数据是否保留。