我需要对一些相关数据进行两个级别的过滤.第一个查询类似于:
SELECT t1.fk_id
FROM t1
LEFT JOIN t3 ON t3.fk_id = t1.fk_id
WHERE t1.field1 > 10 AND t3.field2 = Y
第二个查询针对具有相同fk_id字段的另一个表运行,看起来像
SELECT t2.fk_id, SUM(t2.field3) AS sum_3, SUM(t2.field_4) AS sum_4
FROM t2
WHERE fk_id IN (fk_values_from_query_1)
GROUP BY t2.fk_id
HAVING sum_3 > 1000
现在,我可以说出两种不同的运行方式-尽管我不受任何一种方法的束缚,但也对其他方法开放.我可以将第一个查询作为SUB-SELECT嵌入到第二个查询中,从性能的角度来看,这确实很糟糕.或者,我可以从查询1的结果中提取值,并将它们作为列表嵌入到查询2中(在我的应用程序代码中).
这个问题的两个部分是:
>在性能方面,上述两种查询结构之间是否有区别?
>有没有更好的方法来构造这两个查询?
基准测试
我没有对此进行全面测试,但是针对我的数据运行了我的版本以及Barmar发布的版本.我的查询运行了大约4.23秒,而Barmar的版本仅运行了0.60秒.这是85%的改善!
解决方法:
您应该使用JOIN组合它们:
SELECT t2.fk_id, SUM(t2.field3) AS sum_3, SUM(t2.field_4) AS sum_4
FROM t2
JOIN (SELECT distinct t1.fk_id
FROM t1
JOIN t2 ON t3.fk_id = t1.fk_id
WHERE t1.field1 > 10 AND t3.field2 = 'Y') t4
ON t2.fk_id = t4.fk_id
GROUP BY t2.fk_id
HAVING sum_3 > 1000
我一直发现,与类似的连接相比,MySQL在WHERE col IN(子查询)查询上的表现非常糟糕.我没有将它与替换子查询中的值的查询进行比较,因为我只是在无法在单个查询中完成的情况下才这样做(例如,我需要在不同服务器上匹配数据).
顺便说一句,如果您还要过滤与之连接的表中的值,则使用LEFT JOIN没有意义.
在所有情况下,请确保在join或IN子句中使用的键上具有索引.