2014-05-21 31 views
1

TL;博士 - 大量接受计算器答案建议使用一个子查询来影响由GROUP BY子句返回的行。虽然这起作用,这是最好的建议吗?SQL`组by`与`为了by`性能


据我所知,关于如何检索GROUP BY声明中的特定行已有很多问题。他们大多围绕在FROM条款中使用子查询。子查询将对表格进行适当排序,并将按照现在订购的临时表运行。一些例子,

的PostgreSQL消除了与distinct on()子句子查询的需要。

然而,什么我没有在任何一种情况下理解我有多糟糕拍摄自己的脚试图做一些系统可能没有最初被设计为。看看下面的两个例子在PostgreSQL和MySQL,

在这两种情况下,我都包含相同文章的多个版本的职位表(由它的UUID表示) 。我想选择最近published版本的每个帖子排序的created_at字段。

我最大的担忧是,鉴于MySQL方法,临时表是必需的。棘手的这到“网络规模”(lolz),我想知道如果我在一个受伤的世界。我应该重新思考我的模式还是有办法优化子查询 - 父查询关系,以至于它会好起来的?

回答

2

这是绝对不是最好的建议。 SQL本身(以及我所知道的MySQL文档)几乎没有关于带有order by的子查询的结果。虽然他们可能会在实践中下令,但他们不能保证是。

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

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

一切都来自一个不确定行。具体documentation是(重点是我的):

MySQL的扩展使用GROUP BY的,这样的选择列表可参考 在GROUP BY子句中未命名的非聚合列。这意味着 前面的查询在MySQL中是合法的。您可以使用此功能 以避免不必要的列排序和 分组以获得更好的性能。但是,这对于每个 组中未在GROUP BY中指定的每个 非聚合列中的所有值都相同时都很有用。服务器可以自由选择每组中的任何值,所以 除非它们相同,否则所选值不确定。 此外,每个组的值的选择不能受到添加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 bygroup by更快

+0

这里是理论从实践中转移的地方 - 因为实际上,MySQL(迄今为止)的每个(子查询支持)版本将返回排序结果的第一行,而不管文档建议的内容如何。 – Strawberry

+0

这太好了。我明白选择“行”的风险。然而,从性能的角度来看,如果是两个查询,我能够尽可能地优化这个查询吗?也许这是一个单独的问题......我可以接受并询问另一个问题。 –