这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

GROUP BY 子句

GROUP BY 中将 SELECT 子句与聚合函数一起使用可以收集多个记录中的数据。Vertica 将结果分组成为一个或多个与表达式匹配的行集。

不包含聚合的 GROUP BY 子句的使用方式类似于 SELECT DISTINCT

ROLLUP 是对 GROUP BY 子句的扩展。 ROLLUP 执行小计聚合。

语法

GROUP BY [/*+GBYTYPE(algorithm)*/] { expression | aggregate‑expression }[,...]

参数

/*+GBYTYPE(algorithm)*/
指定实现 GROUP BY 子句时优先级高于 Vertica 查询优化器可能选择的算法的算法。可以将 algorithm 设置为以下值之一:
  • HASHGROUPBY HASH 算法

  • PIPEGROUPBY PIPELINED 算法

有关两种算法的详细信息,请参阅 GROUP BY 实施选项

表达式
任何表达式,包括 FROM 子句中指定的表中的常数和列引用。例如:
column,... column, (expression)
aggregate‑expression
列、表达式、CUBE, GROUPING SETSROLLUP 聚合按顺序排列的列表。

可以将 CUBEROLLUP 聚合包括在一个 GROUPING SETS 聚合内。 CUBEROLLUP 聚合可产生大量输出。在这种情况下,使用 GROUPING SETS 仅返回某些结果。

不能将任何聚合包含在 CUBEROLLUP 表达式中。

可以将多个 GROUPING SETSCUBEROLLUP 聚合附加到同一个查询中。例如:

  
GROUP BY a,b,c,d, ROLLUP(a,b)
GROUP BY a,b,c,d, CUBE((a,b),c,d)
GROUP BY a,b,c,d, CUBE(a,b), ROLLUP (c,d)
GROUP BY ROLLUP(a), CUBE(b), GROUPING SETS(c)
GROUP BY a,b,c,d, GROUPING SETS ((a,d),(b,c),CUBE(a,b))
GROUP BY a,b,c,d, GROUPING SETS ((a,d),(b,c),(a,b),(a),(b),())

用法注意事项

  • 表达式不能包括聚合函数。但是,可以将 GROUP BY 子句与 CUBE、GROUPING SETS 和 ROLLUP 一起使用,以返回每个组的汇总值。

  • 创建 GROUP BY 子句时,必须包括 SELECT 列表中显示的所有非聚合列。

  • 如果 GROUP BY 子句包括 WHERE 子句,Vertica 会忽略所有不满足 WHERE 子句的行。

示例

此示例显示了如何将 WHERE 子句与 GROUP BY 一起使用。在这种情况下,示例检索姓氏以 S 开头的所有员工,忽略所有不符合此条件的行。GROUP BY 子句使用 ILIKE 函数仅检索以 S 开头的姓氏。聚合函数 SUM 计算每个组的总休假天数。

=> SELECT employee_last_name, SUM(vacation_days)
   FROM employee_dimension
   WHERE employee_last_name ILIKE 'S%'
   GROUP BY employee_last_name;
 employee_last_name | SUM
--------------------+------
 Sanchez            | 2892
 Smith              | 2672
 Stein              | 2660
(3 rows)

以下示例中的 GROUP BY 子句按供应商地区和供应商地区的最大交易对结果分组:


=> SELECT vendor_region, MAX(deal_size) AS "Biggest Deal"
   FROM vendor_dimension
   GROUP BY vendor_region;
 vendor_region | Biggest Deal
---------------+--------------
 East          |       990889
 MidWest       |       699163
 NorthWest     |        76101
 South         |       854136
 SouthWest     |       609807
 West          |       964005
(6 rows)

以下查询使用 HAVING 子句修改上一个查询,该子句指定仅返回最大交易规模超过 $900,000 的组:

=> SELECT vendor_region, MAX(deal_size) as "Biggest Deal"
   FROM vendor_dimension
   GROUP BY vendor_region
   HAVING MAX(deal_size) > 900000;
 vendor_region | Biggest Deal
---------------+--------------
 East          |       990889
 West          |       964005
(2 rows)

可以将 GROUP BY 子句与标量类型的一维数组一起使用。在以下示例中,grants 为 ARRAY[VARCHAR],grant_values 为 ARRAY[INT]。

=> CREATE TABLE employees (id INT, department VARCHAR(50), grants ARRAY[VARCHAR], grant_values ARRAY[INT]);

=> COPY employees FROM STDIN;
42|Physics|[US-7376,DARPA-1567]|[65000,135000]
36|Physics|[US-7376,DARPA-1567]|[10000,25000]
33|Physics|[US-7376]|[30000]
36|Astronomy|[US-7376,DARPA-1567]|[5000,4000]
\.

=> SELECT department, grants, SUM(apply_sum(grant_values)) FROM employees GROUP BY grants, department;
 department |          grants          |  SUM
------------+--------------------------+--------
 Physics    | ["US-7376","DARPA-1567"] | 235000
 Astronomy  | ["US-7376","DARPA-1567"] |   9000
 Physics    | ["US-7376"]              |  30000
(3 rows)

不包含聚合的 GROUP BY 子句的使用方式类似于 SELECT DISTINCT。例如,以下两个查询返回相同的结果:

=> SELECT DISTINCT household_id FROM customer_dimension;
=> SELECT household_id FROM customer_dimension GROUP BY household_id;

另请参阅

1 - ROLLUP 聚合

作为 GROUP BY 子句的扩展来自动执行小计聚合。 ROLLUP 在单个 SQL 查询内的不同级别跨多个维度执行聚合。

您可以将 ROLLUP 子句与三个分组函数一起使用:

语法

ROLLUP grouping-expression[,...]

参数

group‑expression
以下两项中的一个或两个:
  • 一个包含常数和 FROM 指定的表中的列引用且不是聚合或分组函数的表达式。例如:

    column1, (column2+1), column3+column4

  • 一个多级表达式,是以下几项之一:

    • ROLLUP

    • CUBE

    • GROUPING SETS

限制

GROUP BY ROLLUP 不会对结果排序。要对数据进行排序,ORDER BY 子句必须跟在 GROUP BY 子句之后。

聚合级别

如果 n 为分组列的数量,则 ROLLUP 将生成 n+1 个小计和总计级别。由于 ROLLUP 将删除每一步中最右侧的列,所以请仔细指定列顺序。

假设 ROLLUP(A, B, C) 创建 4 个组:

  • (A, B, C)

  • (A, B)

  • (A)

  • ()

由于 ROLLUP 将删除每一步中最右侧的列,所以没有 (A, C)(B, C) 组。

如果将 2 个或更多的列括在圆括号内,GROUP BY 会将其视为单一实体。例如:

  • ROLLUP(A, B, C) 将创建 4 个组:

    
    (A, B, C)
    (A, B)
    (A)
    ()
    
  • ROLLUP((A, B), C) 会将 (A, B) 视为单一实体并创建 3 个组:

    (A, B, C)
    (A, B)
    ()
    

示例:聚合完整数据集

以下示例显示了如何使用 GROUP BY 子句确定几年内家庭用电和书籍的开支。SUM 聚合函数计算每年在各类别上的总开销。

假设您有一个表,其中包含关于家庭书籍和用电开支的信息:

=> SELECT * FROM expenses ORDER BY Category, Year;
 Year |  Category   | Amount
------+-------------+--------
2005  | Books       |  39.98
2007  | Books       |  29.99
2008  | Books       |  29.99
2005  | Electricity | 109.99
2006  | Electricity | 109.99
2007  | Electricity | 229.98

对于 expenses 表,ROLLUP 计算 2005–2007 年之间各类别的小计:

  • 书籍:$99.96

  • 用电:$449.96

  • 总计:$549.92。

使用 ORDER BY 子句对结果排序:

=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY ROLLUP(Category, Year) ORDER BY 1,2, GROUPING_ID();
 Category    | Year |  SUM
-------------+------+--------
 Books       | 2005 |  39.98
 Books       | 2007 |  29.99
 Books       | 2008 |  29.99
 Books       |      |  99.96
 Electricity | 2005 | 109.99
 Electricity | 2006 | 109.99
 Electricity | 2007 | 229.98
 Electricity |      | 449.96
             |      | 549.92

示例:将 ROLLUP 与 HAVING 子句一起使用

此示例说明如何将 ROLLUPHAVING 子句一起使用,以限制 GROUP BY 结果。以下查询只生成 ROLLUP 类别,其中 year 根据 GROUPING 函数中的表达式得出小计:

=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY ROLLUP(Category,Year) HAVING GROUPING(Year)=1
   ORDER BY 1, 2, GROUPING_ID();
 Category    | Year |  SUM
-------------+------+--------
 Books       |      |  99.96
 Electricity |      | 449.96
             |      | 549.92

下一个示例对 (Category, Year) 而非完整结果进行汇总。GROUPING_ID 函数指定聚合 3 个以下的级别:

=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY ROLLUP(Category,Year) HAVING GROUPING_ID(Category,Year)<3
   ORDER BY 1, 2, GROUPING_ID();
 Category    | Year |  SUM
-------------+------+--------
 Books       | 2005 |  39.98
 Books       | 2007 |  29.99
 Books       | 2008 |  29.99
 Books       |      |  99.96
 Electricity | 2005 | 109.99
 Electricity | 2006 | 109.99
 Electricity | 2007 | 229.98
 Electricity |      | 449.96

另请参阅

2 - CUBE 聚合

作为 GROUP BY 子句的扩展,自动对指定列执行所有可能的聚合。

您可以将 ROLLUP 子句与三个分组函数一起使用:

语法

GROUP BY group-expression[,...]

参数

group-expression
以下两项中的一个或两个:
  • 一个包含常数和 FROM 指定的表中的列引用且不是聚合或分组函数的表达式。例如:

    column1, (column2+1), column3+column4
    
  • 一个多级表达式,是以下几项之一:

    • ROLLUP

    • CUBE

    • GROUPING SETS

限制

  • GROUP BY CUBE 不对数据排序。如果要对数据排序,请使用 ORDER BY 子句。ORDER BY 子句必须跟在 GROUP BY 子句的后面。
  • CUBE 可以用在 GROUPING SETS 表达式中,但不可以用在 ROLLUP 表达式或另一个 CUBE 表达式中。

CUBE 聚合级别

如果 n 是指分组列的数量,则 CUBE 将生成 2n 个聚合级别。例如:

CUBE (A, B, C) 将生成所有可能的分组,即产生以下八个组:

  • (A, B, C)
  • (A, B)
  • (A, C)
  • (B, C)
  • (A)
  • (B)
  • (C)
  • ()

如果增加 CUBE 列数,则 CUBE 分组数会呈指数增加。CUBE 查询可能会占用大量资源,并产生不感兴趣的组合。在这种情况下,请考虑使用 GROUPING SETS 聚合,因为通过它可以选择特定的分组。

示例

使用 CUBE 返回所有分组

假设您有一个表,其中包含关于家庭书籍和用电开支的信息:

=> SELECT * FROM expenses ORDER BY Category, Year;
 Year |  Category   | Amount
------+-------------+--------
2005  | Books       |  39.98
2007  | Books       |  29.99
2008  | Books       |  29.99
2005  | Electricity | 109.99
2006  | Electricity | 109.99
2007  | Electricity | 229.98

使用 CUBE 聚合按类别和年份聚合数据:

=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY CUBE(Category, Year) ORDER BY 1, 2, GROUPING_ID();
 Category    | Year |  SUM
-------------+------+--------
 Books       | 2005 |  39.98
 Books       | 2007 |  29.99
 Books       | 2008 |  29.99
 Books       |      |  99.96
 Electricity | 2005 | 109.99
 Electricity | 2006 | 109.99
 Electricity | 2007 | 229.98
 Electricity |      | 449.96
             | 2005 | 149.97
             | 2006 | 109.99
             | 2007 | 259.97
             | 2008 |  29.99
             |      | 549.92

结果会包含每个类别和年份的小计以及总计 ($549.92)。

将 CUBE 与 HAVING 子句一起使用

此示例显示了如何限制 GROUP BY 结果以及如何将 CUBE 聚合与 HAVING 子句结合使用。此查询仅返回类别合计和总计:

=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY CUBE(Category,Year) HAVING GROUPING(Year)=1;
 Category    | Year |  SUM
-------------+------+--------
 Books       |      |  99.96
 Electricity |      | 449.96
             |      | 549.92

下一个查询仅返回每个年度两种类别的聚合。GROUPING ID 函数指定忽略总计 ($549.92):

=> SELECT Category, Year, SUM (Amount) FROM expenses
   GROUP BY CUBE(Category,Year) HAVING GROUPING_ID(Category,Year)<2
   ORDER BY 1, 2, GROUPING_ID();
 Category   | Year |  SUM
------------+------+--------
 Books      | 2005 |  39.98
 Books      | 2007 |  29.99
 Books      | 2008 |  29.99
 Books      |      |  99.96
 Electrical | 2005 | 109.99
 Electrical | 2006 | 109.99
 Electrical | 2007 | 229.98
 Electrical |      | 449.96

另请参阅

3 - GROUPING SETS 聚合

GROUPING SETS 聚合是对在您指定的分组上自动执行小计聚合的 GROUP BY 子句的扩展。

您可以将 GROUPING SETS 子句与三个分组函数一起使用:

若要对数据排序,请使用 ORDER BY 子句。ORDER BY 子句必须跟在 GROUP BY 子句之后。

语法

GROUP BY group-expression[,...]

参数

group-expression
以下两项中的一个或两个:
  • 一个包含常数和 FROM 指定的表中的列引用且不是聚合或分组函数的表达式。例如:

    column1, (column2+1), column3+column4

  • 一个多级表达式,是以下几项之一:

    • ROLLUP

    • CUBE

    • GROUPING SETS

定义分组

GROUPING SETS 允许您准确指定结果中需要哪些组。您还可以按照以下方式联接分组:

以下示例子句的分组结果将会显示。

示例:选择分组

此示例显示了如何仅选择您需要的分组。假设您仅希望聚合列,并且您不需要总计。第一个查询会忽略合计。在第二个查询中,您将 () 添加到 GROUPING SETS 列表以获得合计。使用 ORDER BY 子句按分组对结果进行排序:

=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY GROUPING SETS((Category, Year), (Year))
   ORDER BY 1, 2, GROUPING_ID();
  Category  | Year |  SUM
------------+------+--------
 Books      | 2005 |  39.98
 Books      | 2007 |  29.99
 Books      | 2008 |  29.99
 Electrical | 2005 | 109.99
 Electrical | 2006 | 109.99
 Electrical | 2007 | 229.98
            | 2005 | 149.97
            | 2006 | 109.99
            | 2007 | 259.97
            | 2008 |  29.99
=> SELECT Category, Year, SUM(Amount) FROM expenses
   GROUP BY GROUPING SETS((Category, Year), (Year), ())
   ORDER BY 1, 2, GROUPING_ID();
  Category  | Year |  SUM
------------+------+--------
 Books      | 2005 |  39.98
 Books      | 2007 |  29.99
 Books      | 2008 |  29.99
 Electrical | 2005 | 109.99
 Electrical | 2006 | 109.99
 Electrical | 2007 | 229.98
            | 2005 | 149.97
            | 2006 | 109.99
            | 2007 | 259.97
            | 2008 |  29.99
            |      | 549.92

另请参阅