我需要对某些相关数据进行两级过滤。第一个查询类似于:
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%的改善!
答案 0 :(得分:3)
您应该使用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 (subquery)
查询上表现得非常糟糕。我没有将它与我替换子查询中的值的查询进行比较,因为我只是在单个查询中无法完成时才这样做(例如,我需要匹配不同服务器上的数据)。 / p>
顺便说一句,如果您还要对要加入的表中的值进行过滤,则使用LEFT JOIN
毫无意义。
在所有情况下,请确保您在连接或IN
子句中使用的键上有索引。