父表上有WHERE和GROUP BY的多个JOIN

时间:2014-07-03 18:40:44

标签: mysql sql join

我有3个表,一个父项和两个孩子,我正在尝试构建一个查询,该查询聚合来自所有3个字段的字段,并通过完全依赖于父表的表达式进行过滤。为了帮助理解这些表格,第二个孩子在第一个孩子和父母中有一个外键;第一个孩子在父母中有一个外键。例如,


 parentTable | child1Table | child2Table
-------------+-------------+-------------
 id*         | id*         | id
 ...         | subId*      | subId
 ...         | ...         | uniqueId*

*显示构成主键的内容。

我看到两种方法:


SELECT allAggregates
FROM (
    SELECT exprOnParentFields, parentAggregates
    FROM parentTable
    WHERE conditionOnParentRecord GROUP BY exprOnParentFields
  ) full_p
  LEFT JOIN (
    SELECT p.exprOnParentFields, c1.child1Aggregates
    FROM child1Table c1 LEFT JOIN parentTable p ON c1.id = p.id
    WHERE p.conditionOnParentRecord GROUP BY p.exprOnParentFields
  ) full_c1 ON full_p.exprOnParentFields = full_c1.exprOnParentFields
  LEFT JOIN (
    SELECT p.exprOnParentFields, c2.child2Aggregates
    FROM child2Table c2 LEFT JOIN parentTable p ON c2.id = p.id
    WHERE p.conditionOnParentRecord GROUP BY p.exprOnParentFields
  ) full_c2 ON full_p.exprOnParentFields = full_c2.exprOnParentFields

请注意exprOnParentFields在任何地方都是一样的,conditionOnParentRecord也是如此。此外,如果重要,则两者都不一定简单(即只有一个列名)。由于这两件事的重复,我不喜欢这种方法。

备用版本:


CREATE TEMPORARY TABLE filteredIds AS (
  SELECT id, exprOnParentFields AS groupExpr
  FROM parentTable WHERE conditionOnParentRecord);

SELECT allAggregates
FROM (
    SELECT f.groupExpr, p.parentAggregates
    FROM parentTable p INNER JOIN filteredIds f ON p.id = f.id
    GROUP BY f.exprOnParentFields
  ) full_p
  LEFT JOIN (
    SELECT f.groupExpr, c1.child1Aggregates
    FROM child1Table c1 INNER JOIN filteredIds f ON c1.id = f.id
    GROUP BY f.groupExpr
  ) full_c1 ON full_p.groupExpr = full_c1.groupExpr
  LEFT JOIN (
    SELECT f.groupExpr, c2.childAggregates
    FROM child2Table c2 INNER JOIN filteredIds f ON c2.id = f.id
    GROUP BY f.groupExpr
  ) full_c2 ON full_p.groupExpr = full_c2.groupExpr

这样可以节省每个联接的完整exprOnParentFields(现在它只是字段名groupExpr),并消除了conditionOnParentRecord的重复。然而,以创造临时性为代价,它并没有像我希望的那样消除。我的[多部分]问题是:

从风格角度来看,这些是首选之一吗?从速度的角度来看? 或者甚至更好,有没有一种不同的更好的方法来做到这一点?

需要注意的重要一点是,由于重复行的聚合,我无法进行单个3部分连接。

1 个答案:

答案 0 :(得分:1)

简短的回答是“否”。一般来说,我不知道形成查询的更简单或更有效的方法。如果您要加入的每个表都依赖于“之前”的所有表,那么您几乎必须按照您的说法使用SQL。

根据数据更改的频率以及答案的实时接近程度,您可以构建预先汇总在{{1}上的数据的临时副本表达式,以便您可以使用一个计算的结果加入预先聚合的值(即许多查询)。

当然,为了比较这个(和任何东西)的优缺点,你应该总是使用执行计划和跟踪来告诉你db正在做多少工作。

祝你好运!