MySQL多表查询带来的重复记录问题

时间:2019-02-20
本文章向大家介绍MySQL多表查询带来的重复记录问题,主要包括MySQL多表查询带来的重复记录问题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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


假如现在有这么一个需求,

                                                                                                       表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
		)
	)

 这样就可以避免笛卡儿积,来得到我们想要的结果。