tl; dr - 许多可接受的stackoverflow答案建议使用子查询来影响GROUP BY
子句返回的行。虽然这有效,但它是最好的建议吗?
我知道如何检索GROUP BY
语句中的特定行有很多问题。他们中的大多数都围绕在FROM
子句中使用子查询。子查询将适当地对表进行排序,并且group by将针对现在订购的临时表运行。一些例子,
PostgreSQL不再需要带有distinct on()
子句的子查询。
但是,我在任何一种情况下都不理解的是,我试图做一些系统最初可能没有设计的东西,我是多么糟糕。在PostgreSQL和MySQL中采用以下两个例子,
在这两种情况下,我都有一个帖子表,其中包含同一帖子的多个版本(由其UUID表示)。我想选择其published
字段所订购的每篇帖子的最新created_at
版本。
我最担心的是,鉴于MySQL的方法,临时表是必要的。将此提升至"网络规模" (lolz)我想知道我是否有一个受伤的世界。我应该重新考虑我的架构还是有办法优化子查询 - 父查询关系,以便它能够正常运行?
答案 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}}快。