【问题标题】:INNER JOIN versus LIMIT for version版本的 INNER JOIN 与 LIMIT
【发布时间】:2014-06-24 06:37:51
【问题描述】:

在我的第一个问题Multi-Table join need max version for each side 中,我正在使用 INNER JOIN 来合并两个表,这两个表都有需要遵守的“版本”列。我的问题是 - 这与在外部查询结束时使用 ORDER BY version 执行 LIMIT 1 有什么区别?那会更快吗?它甚至以同样的方式工作吗?

 SELECT t1.*, t2.*
 FROM (SELECT t1.*
         FROM t1 ORDER BY t1.id, t1.version LIMIT 1) t1
 LEFT JOIN (SELECT t2.* FROM t2 ORDER by t2.id, t2.version LIMIT 1) t2 
    ON t2.id = t1.ruleId;

【问题讨论】:

  • “它甚至以同样的方式工作吗” --- 看看执行计划。 “这样会更快吗?” --- 现在数据库引擎知道您只需要一行时可能会立即这样做。
  • PS:FROM 子句的嵌套查询看起来是多余的,为什么还要嵌套呢?

标签: sql join optimization


【解决方案1】:

您的查询可能不会返回正确的结果。

首先您可能想使用DESC 来获取MAX 版本:

 SELECT t1.*, t2.*
 FROM (SELECT t1.*
         FROM t1 ORDER BY t1.id, t1.version DESC LIMIT 1) t1
 LEFT JOIN (SELECT t2.* FROM t2 ORDER by t2.id, t2.version DESC LIMIT 1) t2 
    ON t2.id = t1.ruleId;

但即使进行了这种更正,也会出现不匹配的情况。

以这个案例为例:

t1:
id ruleid version
1  1      1
1  2      2
2  1      1
2  2      2
2  3      3

您对 t1 的子查询将选择这一行:

SELECT t1.* FROM t1 ORDER BY t1.id, t1.version DESC LIMIT 1

t1:
id ruleid version
1  2      2

它将始终返回 id=1 的一行。即使您使用#3 和版本#100 添加 id,LIMIT 子句也会根据您的 ORDER BY t1.id, t1.version DESC 子句限制选择

现在,让我们检查一下 t2。要使 t2 具有这些值:

t2:
id version
1  1
1  2
2  1
2  2
2  3

子查询将选择这一行:

SELECT t2.* FROM t2 ORDER by t2.id, t2.version DESC LIMIT 1

t2:
id version
1  2

如您所见,t2.id 不会与 t1.ruleid 加入

作为对您之前问题的回答而提出的查询:

SELECT t1.*, t2.*
 FROM (SELECT t1.*
         FROM t1
         JOIN (SELECT id, MAX(version) AS "VERSION"
                 FROM t1
                GROUP BY id) MAX_T1  ON MAX_T1.id = t1.id 
                                    AND MAX_T1.version = t1.version
      ) t1
 LEFT JOIN (SELECT t2.*
              FROM t2
              JOIN (SELECT t2.id, MAX(t2.version) AS "VERSION"
                      FROM t2
                     GROUP BY t2.id) MAX_T2  ON MAX_T2.id = t2.id 
                                            AND MAX_T2.version = t2.version
           ) t2 ON t2.id = t1.ruleId
;

将返回正确的匹配:t2.id 将匹配 t1.ruleid

顺便说一句,您只能将查询用于“已知”ID。例如。如果您需要为 ID=3 选择最大版本,查询将如下所示:

 SELECT t1.*, t2.*
 FROM (SELECT t1.*
         FROM t1 WHERE ruleid=3 ORDER BY t1.id, t1.version DESC LIMIT 1) t1
 LEFT JOIN (SELECT t2.* FROM t2 WHERE id=3 ORDER by t2.id, t2.version DESC LIMIT 1) t2 
    ON t2.id = t1.ruleId
 WHERE t2.id = 3;

【讨论】:

    【解决方案2】:

    您想要最新的 t1 和最新的 t2。对吧?

    SELECT t1.*, t2.*
    FROM       t1
    INNER JOIN t2 on t2.id = t1.ruleId
    ORDER BY t1.version DESC, t2.version DESC
    LIMIT 1
    

    【讨论】:

    • 只返回一行。
    • 我很难理解您的原始查询是如何返回多行的。您正在将 t1 上的一个查询的结果加入到一个结果中,t2 上的另一个查询仅限于一个结果。那怎么可能返回不止一行?
    猜你喜欢
    • 2018-05-10
    • 1970-01-01
    • 2021-01-18
    • 2021-08-07
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2013-07-19
    相关资源
    最近更新 更多