3

我需要对一些相关数据进行两级过滤。第一个查询类似于:

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 中(在我的应用程序代码中)。

这个问题的两个部分是:

  1. 上述两种查询结构之间在性能方面有什么区别吗?
  2. 有没有更好的方法来构建这两个查询?

基准

我没有对此进行全面测试,而是针对我的数据运行了我的版本以及 Barmar 发布的版本。我的查询运行了大约 4.23 秒,而 Barmar 的版本只用了 0.60 秒。这是一个 85% 的改进!

4

1 回答 1

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

WHERE col IN (subquery)与类似的连接相比,我一直发现 MySQL 在查询上的表现非常糟糕。我没有将它与我替换子查询中的值的查询进行比较,因为我只是在单个查询中无法做到这一点时才这样做(例如,我需要匹配不同服务器上的数据)。

LEFT JOIN顺便说一句,如果您还要过滤正在连接的表中的值,那么使用 a 是没有意义的。

在所有情况下,请确保您对连接或IN子句中使用的键具有索引。

于 2013-05-06T17:32:45.930 回答