如何在 SQL 中实现嵌套聚合查询?

先通过子查询或CTE分步实现嵌套聚合,再进行二次聚合。例如计算各区域总销售额的平均值:先按region分组求sum(amount),再对外层结果求avg(total_sales),必须为子查询命名且外层仅能引用其选择字段。

在 SQL 中实现嵌套聚合查询,通常需要借助子查询或公用表表达式(CTE),因为大多数数据库不允许直接在一个聚合函数内嵌套另一个聚合函数。例如,你不能直接写 AVG(SUM(sales)),但可以通过分步方式先进行分组聚合,再对结果进一步聚合。

使用子查询实现嵌套聚合

最常见的方法是将第一层聚合放在子查询中,外层再对子查询的结果进行第二次聚合。

假设有一个销售表 sales,包含字段:region、product、amount。你想计算“每个区域总销售额的平均值”:
  • 先按 region 分组,求出每个区域的总销售额
  • 再对外层结果求平均

SQL 示例:


SELECT AVG(total_sales) AS avg_region_sales
FROM (
  SELECT region, SUM(amount) AS total_sales
  FROM sales
  GROUP BY region
) AS region_totals;

这个查询首先得到每个区域的总销售额,然后计算这些总和的平均值。

使用 CTE 提高可读性

对于复杂逻辑,使用 CTE 可让代码更清晰。


WITH region_totals AS (
  SELECT region, SUM(amount) AS total_sales
  FROM sales
  GROUP BY region
)
SELECT AVG(total_sales) AS avg_region_sales,
       MAX(total_sales) AS max_region_sales
FROM region_totals;

这种方式逻辑分层明确,便于调试和扩展。

处理多层级分组场景

有时需要多级聚合,比如先算每个产品在每个区域的销售额,再算区域总和,最后统计高于平均值的区域数量。


WITH product_region_sum AS (
  SELECT region, product, SUM(amount) AS prod_reg_sales
  FROM sales
  GROUP BY region, product
),
region_total AS (
  SELECT region, SUM(prod_reg_sales) AS total_sales
  FROM product_region_sum
  GROUP BY region
)
SELECT COUNT(*) AS above_avg_count
FROM region_total
WHERE total_sales > (SELECT AVG(total_sales) FROM region_total);

这种结构可以灵活支持深度聚合分析。

基本上就这些。关键是把聚合拆解成步骤,用子查询或 CTE 组织逻辑。不复杂但容易忽略的是:必须给子查询起别名,且外层不能直接引用内层未选中的字段。