我在MySQL中的查询如下所示:
SELECT *, min(start_date_time) as min_start_date_time
FROM result_table
where part_number= '101'
group by part_serial;
我希望查询会按part_serial
对结果进行分组,然后创建一个新列'min_start_date_time'
,对于给定的{{1},每列的最小start_date_time
}}
但我得到的是,每个part_serial
只有一行,其中part serial
是给定start_date_time
的最小值。
有人可以解释此查询的执行流程吗?
答案 0 :(得分:0)
除了为聚合函数计算创建边界之外,听起来您期望GROUP BY子句更像ORDER BY子句,只是在结果中强制组中的行彼此相邻。不是这种情况。 GROUP BY子句实际上会将结果集过滤为每组一行。
有人可以解释此查询的执行流程
我会抓住它,但请记住,这是一个非常简化的流程。获得比这更复杂的事情并不需要太多,并且当查询引擎认为它可以产生更快或更有效的计划时,数据库可以使用统计和索引来更改此基本查询流。我也不能把它留给这个查询,因为解释流程流程时至少没有给JOIN提供过一点小费,而其他复杂性会产生一些误导性的解释。这个免责声明,让我们开始吧。
该过程从规划阶段开始,以识别表空间。也就是说,数据库计算FROM子句使用的表以及任何JOIN中的表或视图的匹配规则。除了记录指针或主键之外,它实际上并没有将任何内容加载到内存中。现在,它只是计算表的匹配规则,并确定完成连接和构建结果行的最有效方法。
例如,您可以加入一个包含5列的表,其中连接条件与第三列中的外键匹配,但表的主键是第一列,而选择列表最终只使用来自第四栏。在此阶段,数据库正在构建计划,以便以最快的方式为原始表的每个记录加载第四列数据。可能有一个索引可以使用第3列和第4列来满足查询,或者它可能需要通过第1列中的主键从原始表中加载数据。做出这种决定是这里涉及的内容。
对于像这个问题一样的单表查询,所有这些通常只是确定是否可以从索引完全满足查询,但它仍然是该过程的重要部分。
完成后,数据库开始检查查询的main / original表中的行。数据库将首先应用WHERE子句的相关部分(希望充分利用索引),以保持工作集较小。然后,它会为任何符合上一步骤中确定的规则的联接表提取数据。它应用WHERE子句中的任何剩余元素,希望在连接表上使用有用的索引...再次,以保持查询的内存和磁盘使用尽可能低,并尽快释放不必要的信息可能。
有时,当一个连接与目标表中的多个记录匹配时,此过程将实现新行,但该过程将继续,直到计算出原始行的整个结果为止。
在完成每个实现行时,可以应用GROUP BY子句。这通过查看行并识别行所属的组来工作。此时,该行被合并(未复制)到新的工作集中(如果没有GROUP BY子句,则可以跳过此行)。如果新集合已经有一个与该组匹配的行,则它只更新任何聚合函数计算(为该组添加1到COUNT,检查我们是否有新的MAX或MIN,更新最终将允许AVG计算的SUM等)。如果新集合中还没有该行的行,则会在集合中创建一行,其中包含当前行的种子数据。当数据库完成原始集合中的行时,可以将其丢弃。完成整个GROUP BY子句后,查询不再需要原始工作集。
此时,可以评估HAVING子句(如果有的话)以及ORDER BY子句。
最后,数据库开始将结果流式传输到客户端应用程序。在对每一行进行流式处理时,将执行SELECT子句指定的任何转换,并将其包含在最终结果集中。请注意,如果您没有GROUP BY,ORDER BY子句,DISTINCT或窗口函数,则只要第一个记录准备就绪,就可以开始流式传输。如果您有任何这些内容,则必须构建整个结果集,以便了解如何进行流式处理,直到 last 记录准备好后才能开始。就初始延迟和服务器上的资源使用而言,这可以巨大。