Left Join和Inner Join的体会
有字典表zs_dic
BelongTable |
所属数据库表 |
BelongField |
所属字段 |
fieldvalue |
记录值 |
displayvalue |
显示值 |
有下面一个sql语句,zs_contract表的pro_property字段和qualification字段的显示值记录在字典表中,现在查询的时候要查找它们的显示值
SELECT dbo.zs_contract.pro_name, dbo.zs_contract.build_com, dbo.zs_contract.con_prise,
dbo.zs_contract.con_no,
dbo.zs_design_sheet.sheet_no,
signtime,
zs_dic_1.displayvalue AS qualification,
dbo.zs_dic.displayvalue AS pro_property
FROM dbo.zs_contract INNER JOIN
dbo.zs_design_sheet ON dbo.zs_contract.id = dbo.zs_design_sheet.id
inner JOIN
dbo.zs_dic ON dbo.zs_contract.pro_property = dbo.zs_dic.fieldvalue
inner JOIN
dbo.zs_dic zs_dic_1 ON dbo.zs_contract.qualification = zs_dic_1.fieldvalue
WHERE
(zs_dic_1.belongtable = 'zs_contract') AND (zs_dic_1.belongfield = 'qualification')
and
(dbo.zs_dic.belongtable = 'zs_contract') AND (dbo.zs_dic.belongfield = 'pro_property') (注意这里)
AND
(dbo.zs_design_sheet.design_id = '08DEE415-EEB3-4F0D-A923-B9A38C6793AF')
查询关系如下图
但是由于种种原因,pro_property字段的值允许输入null值,结果导致上面的sql语句查询值为空。后将
inner JOIN
dbo.zs_dic ON dbo.zs_contract.pro_property = dbo.zs_dic.fieldvalue
改为:
Left JOIN
dbo.zs_dic ON dbo.zs_contract.pro_property = dbo.zs_dic.fieldvalue
仍然无效。
后来经过思考,(dbo.zs_dic.belongtable = 'zs_contract') AND (dbo.zs_dic.belongfield = 'pro_property') 语句是对pro_property的限定,要找满足belongtable = 'zs_contract'和zs_dic.belongfield = 'pro_property'的且pro_property字段值等于fieldvalue的displayvalue。zs_contract为左表,zs_dic为右表,而left jion的作用现在只对dbo.zs_dic ON dbo.zs_contract.pro_property = dbo.zs_dic.fieldvalue起作用,而belongtable = 'zs_contract'和zs_dic.belongfield = 'pro_property'是在where后面的,表示一定要满足,但是如果满足where的条件,则fieldvalue只能为非null的值,自然就查不到了。后将代码改为:
SELECT dbo.zs_contract.pro_name, dbo.zs_contract.build_com, dbo.zs_contract.con_prise,
dbo.zs_contract.con_no,
dbo.zs_design_sheet.sheet_no,
signtime,
zs_dic_1.displayvalue AS qualification,
dbo.zs_dic.displayvalue AS pro_property
FROM dbo.zs_contract INNER JOIN
dbo.zs_design_sheet ON dbo.zs_contract.id = dbo.zs_design_sheet.id
left JOIN
dbo.zs_dic ON dbo.zs_contract.pro_property = dbo.zs_dic.fieldvalue
and
(dbo.zs_dic.belongtable = 'zs_contract')
AND
(dbo.zs_dic.belongfield = 'pro_property') (修改后)
inner JOIN
dbo.zs_dic zs_dic_1 ON dbo.zs_contract.qualification = zs_dic_1.fieldvalue
WHERE
(zs_dic_1.belongtable = 'zs_contract') AND (zs_dic_1.belongfield = 'qualification')
AND
(dbo.zs_design_sheet.design_id = '08DEE415-EEB3-4F0D-A923-B9A38C6793AF')
将where后面的条件移到left join里,则查询正常,可以满足pro_property为null或不为null的情况。
由此得出经验:在上例中,如果要对右表做出一些非列关联的条件过滤,例如要求某列值等于一个固定的值(如:zs_dic.belongfield = 'pro_p roperty'),如果右表中可能出现与左表不匹配的数据,除了用left join外,还要注意不要将这些过滤条件放在where后面,而应该放在left join后面。
另外,使用where语句时应注意区分左右表的关联方式,在where语句中注意过滤的条件,见下表
关联方式 |
注意的问题 |
A left join B |
不要在where语句中加入对B表的过滤,在left jion后面加 |
A right join B |
不要在where语句中加入对A表的过滤,在right join 后面加 |
A inner join B |
—— |