【问题标题】:How to think of aggregate functions in terms of sets如何从集合的角度考虑聚合函数
【发布时间】:2009-09-08 01:51:54
【问题描述】:

我试图从集合的角度来考虑数据,但对聚合函数有一些疑问。

这是来自维基的定义

聚合函数是一个函数 从 a 返回单个值 输入值的集合,例如 设置

例如,

select c.id, c.user_id, c.name, c.created_at, count(c.id) from collections c;

可以认为“count从集合c集合中返回单个值”

select c.id, c.user_id, c.name, c.created_at, count(c.id) 
from collections c group by c.user_id

可以认为“count从一个collection(c) set的每个子集(set from group by)中返回一个值”

我的问题是,我如何知道计数从哪个“单个值”返回,在这种情况下,是 collection(c) 集合或每个“分组依据”子集。

考虑一个稍微复杂的查询(TOP N PER GROUP)

select c.id, c.user_id, c.name, c.created_at 
from collections c 
left join collections co on c.user_id = co.user_id and c.name <=co.name 
group by c.user_id, c.name 
having count(*)<=2;

这里设置 group by(c.user_id) 有自己的子集 (c.name),我怎么知道 count(*) 将返回什么(整个集合的单个值(这将只是一个rol)? 或每个子集的单个值(c.user_id) 或每个子集的单个值(c.name)?)

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    对于任何执行聚合的查询,您需要按正确的字段进行分组。

    第一个查询应该会失败,因为 c.id、c.user_id、c.name 和 c.created_at 字段没有使用 GROUP BY 进行分组。

    同样,第二个查询也会失败,因为只有第一个字段被分组。

    要使最后一个查询正常工作,您可能还需要在 GROUP BY 中包含 id。

    只有当 SELECT 子句的所有非聚合元素(例如 c.id、c.user_id 等)都代表正在聚合的组(即包含在 GROUP BY 子句中)时,聚合函数才起作用。

    【讨论】:

    • 我很确定 MySQL 在执行该要求方面很松懈,实际上会执行查询 2 和 3。
    • 很高兴知道,但我认为它在这方面与 SQL 标准保持足够接近
    • 谢谢。查询 1、2 和 3 将在 mysql 中执行。我在发布之前尝试了这些查询。 mysql 不强制执行任何这些要求,但仅在聚合时才有意义。
    【解决方案2】:

    GROUP BY 不会创建多个集合。它使一个;在您的情况下,它按对(c.user_id,c.name)分组。任何具有相同 (c.user_id, c.name) 的行都放在一个组中,这些是 count(*) 将处理的组。

    【讨论】:

      【解决方案3】:

      聚合函数在计算之后 a) 加入 b) 根据 where 子句过滤行。

      连接完成并根据查询中的 where 子句过滤行后,想象一下您的数据集。 group by 子句现在将根据 where 子句中指定的列将数据集细分为不同的组。对于 where 子句中指定的所有列,给定组中的所有行都将具有相同的值。

      一旦原始数据集中的行被分组,您只能查询(即选择列)组共有的。在您按 c.user_id 分组的第二个示例中,您的集合表中的每个不同的 user_id 将有一个组。如果您的查询中没有“HAVING”子句,您的查询将返回每组一行。您可以将每个组视为(仅将其视为)包含列的行。这些列将代表整个组共有的事物,例如 count(*)、SUM、MAX、MIN 等。组成组的列名对于每个组也是相同的!

      having 子句类似于用于组的 where 子句。它过滤掉不满足have子句中谓词的整个组。

      【讨论】:

        猜你喜欢
        • 2020-04-19
        • 2015-06-28
        • 2021-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多