SQL`group by`与`order by ... Performance

时间:2014-05-21 13:49:26

标签: mysql sql postgresql group-by sql-order-by

tl; dr - 许多可接受的stackoverflow答案建议使用子查询来影响GROUP BY子句返回的行。虽然这有效,但它是最好的建议吗?


我知道如何检索GROUP BY语句中的特定行有很多问题。他们中的大多数都围绕在FROM子句中使用子查询。子查询将适当地对表进行排序,并且group by将针对现在订购的临时表运行。一些例子,

PostgreSQL不再需要带有distinct on()子句的子查询。

但是,我在任何一种情况下都不理解的是,我试图做一些系统最初可能没有设计的东西,我是多么糟糕。在PostgreSQL和MySQL中采用以下两个例子,

在这两种情况下,我都有一个帖子表,其中包含同一帖子的多个版本(由其UUID表示)。我想选择其published字段所订购的每篇帖子的最新created_at版本。

我最担心的是,鉴于MySQL的方法,临时表是必要的。将此提升至"网络规模" (lolz)我想知道我是否有一个受伤的世界。我应该重新考虑我的架构还是有办法优化子查询 - 父查询关系,以便它能够正常运行?

1 个答案:

答案 0 :(得分:2)

绝对不是最好的建议。 SQL本身(以及据我所知的MySQL文档)对具有order by的子查询的结果几乎没有什么可说的。虽然它们可能在实践中被命令,但不能保证它们。

更重要的问题是在聚合中使用“隐藏列”。考虑这个基本查询:

select t.*
from (select t.* from table t order by datecol) t
group by t.col;

t.col中除select之外的所有内容都来自不确定行。具体的documentation是(重点是我的):

  

MySQL扩展了GROUP BY的使用,以便选择列表可以引用   未在GROUP BY子句中命名的非聚合列。这意味着   前面的查询在MySQL中是合法的。您可以使用此功能   通过避免不必要的列排序来获得更好的性能   分组。 但是,这主要适用于每个值中的所有值   GROUP BY中未命名的非聚合列对于每个列都是相同的   group。服务器可以自由选择每个组的任何值,所以   除非它们相同,否则所选择的值是不确定的。   此外,不能从每个组中选择值   受添加ORDER BY子句的影响。对结果集进行排序   选择值后发生,ORDER BY不影响   服务器选择的每个组中的值。

编写此类查询的安全方法是:

select t.*
from table t
where not exists (select 1
                  from table t2
                  where t2.col = t.col and t2.datecol < t.datecol
                 );

这不完全相同,因为如果最小值不唯一,它将返回多个值。逻辑是“让我在表格中的所有行中没有具有相同col值和较小datecol值的行。

编辑:

评论中的问题没有意义,因为没有讨论两个问题。在MySQL中,您可以使用order by和变量来解决这个问题:

select t.*
from (select t.*,
             @rn := if(@col = col, @rn := @rn + 1, 1) as rn,
             @col := col
      from table t cross join
           (select @col := '', @rn := 0) vars
      order by col, datecol) t
where rn = 1;

这种方法应该比带有order by的{​​{1}}快。