首页 > 解决方案 > 是否有更清晰的方法来处理不在聚合函数或 GROUP BY 子句中的字段?

问题描述

我经常遇到这样的查询:

SELECT
    a.Id,
    a.A,
    a.B,
    a.C,
    SUM(b.Foo) AS foo
FROM
    TableA AS a
    JOIN TableB AS b
        ON a.Id = b.TableAId
GROUP BY a.Id;

在 SQL Server(如果为真,还有 MySQL ONLY_FULL_GROUP_BY)中,这个查询不好。一切都必须是 a) 在聚合函数中,或 b) 在GROUP BY.

我的问题是这两种解决方案看起来都很糟糕且具有误导性。如果你选择一个随机聚合函数,MAX()你最终会得到:

SELECT
    a.Id,
    MAX(a.A) AS A,
    MAX(a.B) AS B,
    MAX(a.C) AS C,
    SUM(b.Foo) AS foo
FROM
    TableA AS a
    JOIN TableB AS b
        ON a.Id = b.TableAId
GROUP BY a.Id;

这个查询看起来像我们关心 、 和 的最大值a.Aa.B并且a.C混淆了最大值没有意义的事实。

GROUP BY好一点:

SELECT
    a.Id,
    a.A,
    a.B,
    a.C,
    SUM(b.Foo) AS foo
FROM
    TableA AS a
    JOIN TableB AS b
        ON a.Id = b.TableAId
GROUP BY a.Id, A, B, C;

但它仍然不是最佳的。在具有复杂分组的大查询中,拥有所有这些额外的字段会使阅读变得更加困难,我最初的印象是这里有一些实际上并不存在的额外分组层次结构。

我的背景主要是在 MySQL 中ONLY_FULL_GROUP_BY关闭,所以我发现 SQL Server 中的这个限制是不必要的。我希望两者之间有一些快乐的媒介;TableA计算机查看此查询并看到不需要聚合字段,而来自TableB(besides TableAId)的任何字段都需要聚合,这似乎是一件简单的事情。

有什么想法吗?

标签: mysqlsqlsql-serveraggregation

解决方案


这不是 SQL Server 问题!您看到的行为是 MySQL 损坏(通常),这就是为什么现在的默认设置是禁止该行为。也就是说,SQL 标准允许通过表中的唯一列进行聚合并选择表中的其他列。但是,我认为只有 Postgres 实现了这一点。

这是您遗漏的一种方法:

SELECT a.*, b.foo
FROM TableA a JOIN
     (SELECT b.TableAId, SUM(b.Foo) as foo
      FROM TableB b
      GROUP BY b.TableAId
     ) b
     ON a.Id = b.TableAId;

推荐阅读