在开发中因为不谨慎遇到了这样一个问题,这里总结一下问题、问题出现的原因和解决方式。
假如现在有这么一个需求,
表1

表2

想要从表1中筛选出masterMerchantNo或slaveMerchantNo其中任意一个字段的值等于表2的merchantNo(也就是在表2中的merchantNo中存在这个值)的所有记录的表1的相关信息。
所以我一开始想到的是两表查询然后过滤条件,也就是两个条件OR就可以了(tb1.masterMerchantNo = tb2.merchantNo OR tb1.slaveMerchantNo = tb2.merchantNo),原先编写的sql如下:
SELECT
tb1.batchNo,
tb1.masterSettleUnitID,
tb1.masterMerchantNo,
tb1.slaveSettleUnitID,
tb1.slaveMerchantNo,
tb1.activityType,
tb1.operatorInfo,
tb1.submitTime,
tb1.bindStatus,
tb1.returnCode,
tb1.returnMsg,
tb1.unbindTime
FROM
tbl_fsm_settle_activity_mergeRecord tb1
INNER JOIN (
SELECT
merchantNo
FROM
tbl_fsm_settle_unit
WHERE
groupID = 1155
AND openPayStatus = 40
) tb2 ON tb1.masterMerchantNo = tb2.merchantNo
OR tb1.slaveMerchantNo = tb2.merchantNo
WHERE
action in ( 0 , 1 )
然后发现了问题,正常按照需求想要的结果应该是筛选后只有一条记录,就是表1这样的一条,然而如果是上面这样的sql的话,执行完后会得到两条记录,而且两条记录是一模一样的。。这显示不是我们想要的。
思考了下,发现原因,像上面这样的写法的话,sql执行首先会生成笛卡儿积,表1*表2,也就是1*2=2,总共生成2条记录,笛卡儿积应该如下:

然后在对上图所示笛卡儿积进行条件(tb1.masterMerchantNo = tb2.merchantNo OR tb1.slaveMerchantNo = tb2.merchantNo)过滤,所以这样就会得到两条重复的结果。。
所以解决这个问题的方式就是要避免笛卡儿积,所以我们避免使用多表查询sql,可以使用如下的sql:
SELECT
batchNo,
masterSettleUnitID,
masterMerchantNo,
slaveSettleUnitID,
slaveMerchantNo,
activityType,
operatorInfo,
submitTime,
bindStatus,
returnCode,
returnMsg,
unbindTime
FROM
tbl_fsm_settle_activity_mergeRecord
WHERE
action IN (0, 1)
AND (
masterMerchantNo IN (
SELECT
merchantNo
FROM
tbl_fsm_settle_unit
WHERE
groupID = 1155
AND openPayStatus = 40
)
OR slaveMerchantNo IN (
SELECT
merchantNo
FROM
tbl_fsm_settle_unit
WHERE
groupID = 1155
AND openPayStatus = 40
)
)
这样就可以避免笛卡儿积,来得到我们想要的结果。
本文通过一个具体的案例,详细解析了在SQL查询中如何避免笛卡尔积的产生,从而有效地筛选出符合特定条件的数据记录。文章对比了两种查询方法,一种是直接使用OR连接的多表查询,另一种是通过子查询避免笛卡尔积的方法,最终得出了正确的查询结果。
1336

被折叠的 条评论
为什么被折叠?



