您如何优化连接自身并执行“自定义”分组的 MySQL 查询?

Posted

技术标签:

【中文标题】您如何优化连接自身并执行“自定义”分组的 MySQL 查询?【英文标题】:How do you optimize a MySQL query that joins on itself and does a "custom" group by? 【发布时间】:2013-05-04 03:29:53 【问题描述】:

随着数据库表大小的增加,我的以下查询开始变慢:

SELECT  
    t.*, 
    e.TranslatedValue AS EnglishValue
FROM (
    SELECT DISTINCT PropertyKey 
    FROM Translations
) grouper
JOIN Translations t 
    ON t.TranslationId = (
        SELECT TranslationId 
        FROM Translations gt
        WHERE gt.PropertyKey = grouper.PropertyKey 
            AND gt.Locale = 'es' 
            AND gt.Priority = 3
        ORDER BY gt.ModifiedDate DESC 
        LIMIT 1
    )
INNER JOIN Translations e 
    ON t.EnglishTranslationId = e.TranslationId 
ORDER BY t.ReviewerValidated, PropertyKey

首先,我从 Translations 中选择所有内容,并将其与自身相结合,以获得相应的英文值。

然后,我想将结果限制为每个 PropertyKey 一个。这就像一个 group by,除了我需要选择一个特定的记录作为返回的记录(而不是 group by 只给我它找到的第一个记录)。这就是为什么我有只返回一个 TranslationId 的内部查询。

当我运行解释时,我得到以下信息:

有没有一种方法可以返回相同的结果集,而不必让 mysql 使用较慢的派生表?谢谢!

更新:我创建了一个带有架构和示例数据的 SQL Fiddle。你可以 自己运行我的查询以查看它给出的结果。我需要成为 能够获得相同的结果,希望以更快的方式。 http://sqlfiddle.com/#!2/44eb0/3/0

【问题讨论】:

你能提供样本数据和你想要的结果吗? MySQL 应该在你执行查询时报错,因为 ORDER BY 子句中的 PropertyKey 是不明确的(有三个,即使它们相等)。 @newtover - 它不会抱怨,因为该级别只有一个 PropertyKey(其他的在子查询中)。如果你想坚持一个t。为了清楚起见,在它前面,这很好。 @GordonLinoff 感谢您提供查看示例数据和结果。有没有办法将文件附加到 SO 问题?有没有类似 JSFiddle for MySQL 的服务? @GordonLinoff 我用我需要的模式、数据和结果创建了一个 SQL Fiddle:sqlfiddle.com/#!2/44eb0/3/0 【参考方案1】:

我认为您想要与记录中的PropertyKey 匹配的给定本地和优先级的最新TranslatedValue

如果是这样,以下是您想要的,使用单个相关子查询:

 select t.*,
        (select t2.TranslatedValue
         from Translations t2
         where t.PropertyKey = t2.PropertyKey and
               t2.Locale = 'es' and
               t2.Priority = 3
         order by t.ModifiedDate desc
         limit 1
        ) as EnglishValue
 from Translations t
 having EnglishValue is not NULL
 ORDER BY t.ReviewerValidated, PropertyKey;

having 子句删除没有翻译的记录。)

如果是这样,那么Translations(PropertyKey, Locale, Priority, ModifiedDate) 上的索引应该会加快查询速度。

【讨论】:

感谢@Gordon Linoff,但我仍然没有得到我需要的东西。我首先必须稍微更改您的查询:t2.Locale = 'es' 和 t2.Priority = 3 应该更改为 t.Locale = 'es' 和 t.Priority = 3。我还必须添加 where t2.Locale = 'en' 因为我在 EnglishValue 字段中获得了各种语言。现在数据和我的查询完全一样,除了 PropertyKey 上还有重复。 @11101101b 。 . .当然,PropertyKey 上有重复项。您没有进行最终分组。如果这是您想要的输出,您可以添加 group by PropertyKey 我试过@Gordon Linoff,但你必须在拥有和订购之前进行分组(这并没有给我我想要的)。 我创建了一个 SQL Fiddle。我用指向 Fiddle 的链接修改了我的问题(允许您对我的示例模式和数据实际运行查询)。我也有一个尝试实现您的查询的小提琴(sqlfiddle.com/#!2/44eb0/6/0)。如您所见,结果并不相同。

以上是关于您如何优化连接自身并执行“自定义”分组的 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用自定义列对连接表进行分组

mysq解决sleep进程过多的办法

如何正确连接并显示从 Firebase 到自定义列表视图 Android Studio 的数据

如何按字段对文档进行分组并使用带有 CouchDB 视图的自定义 reduce 函数列出不相等的值

如何优化Oracle在where条件中用了自定义函数的SQL语句

在同一连接器的流程中使用自定义连接器的组件