假如现在有两张表,表A:

多表关联查询如果剑索引 多表关联查询求和_字段


表B:

多表关联查询如果剑索引 多表关联查询求和_sql_02


tableA和tableB通过index关联

现在的需求是已知tableA的batchNo,需要求该batchNo对应的sum(column1)和sum(column3),我们先尝试下left join

多表关联查询如果剑索引 多表关联查询求和_sql_03


明显可以看出,join后的结果有三条,依照这种结果来求column1的和会出错。由于batchNo和index是一对多的关系,而在B表中index相同的记录可能会有多条,联表查询的条数等于两张表中对应记录较多的表的记录条数,而需求是一次将两张表中对应指定字段的和求出,除非刚好两张表中记录条数一致否则就会有某一张表中的字段和出错。

那最后解决办法是什么呢?贴一个简单示例

SELECT batchNo, SUM(column1Sum) column1Sum, SUM(column2Sum) column2Sum
FROM
(
SELECT batchNo, SUM(column1) column1Sum, 0 column2Sum FROM tableA
WHERE batchNo = 'x' GROUP BY batchNo

UNION

SELECT '' batchNo, 0 column1Sum, SUM(column3) column2Sum FROM tableB b
WHERE b.`index` IN
(
SELECT `index` FROM tableA a WHERE a.batchNo = 'x'
)
GROUP BY `index`
) aa GROUP BY batchNo

多表关联查询如果剑索引 多表关联查询求和_多表关联查询如果剑索引_04


是不是有模有样了,最后按照batchNo求和即可,但是表B里没有batchNo啊,没关系,再套一层

SELECT batchNo, SUM(column1Sum) column1Sum, SUM(column2Sum) column2Sum
FROM
(

SELECT batchNo, SUM(column1) column1Sum, 0 column2Sum FROM tableA
WHERE batchNo = 'x' GROUP BY batchNo

UNION

SELECT a.batchNo batchNo, 0 column1Sum, SUM(column2Sum) column2Sum FROM
(
SELECT `index`, SUM(column3) column2Sum FROM tableB b GROUP BY `index`
)c LEFT JOIN tableA as a ON c.`index` = a.`index` 
WHERE a.batchNo = 'x' GROUP BY a.batchNo

) aa GROUP BY batchNo

多表关联查询如果剑索引 多表关联查询求和_多表关联查询如果剑索引_05


完美解决!可以根据需要改成批量查询,虽然这个SQL看起来复杂,真正的查询部分只是最内层有,外层只是对数据进行处理,所以速度不会很慢。

简单介绍一下思路:

分别对两张表中对应的字段求和,对不需要的字段设为0并且重命名,相当于构建一张子表,然后使用union将两张子表合并,最后再求一次和得出最终结果。需要注意union的连接的表字段要一致。

好处是能满足需求,坏处是很看起来确实不是很好理解哈哈哈,说不定写完过一个星期自己都看不懂了。我的需求要联五张表,写出来一大坨,但其实每个子查询都是相对独立的,排查的时候由内往外,耐心一点。如果没有要求,其实可以分开查询每个和。

如果有大佬有更好的解决方式,欢迎指点一二。