类别:

查询语法

GROUP BY

使用相同的逐项分组表达式对行进行分组,并计算结果组的聚合函数。GROUP BY 表达式可以是:

  • 列名称。

  • 引用 SELECT 列表中位置的数字。

  • 通用表达式。

扩展:

GROUP BY CUBEGROUP BY GROUPING SETSGROUP BY ROLLUP

语法

SELECT ...
  FROM ...
  [ ... ]
  GROUP BY groupItem [ , groupItem [ , ... ] ]
  [ ... ]
Copy
SELECT ...
  FROM ...
  [ ... ]
  GROUP BY ALL
  [ ... ]
Copy

其中:

GROUP BY groupItem [ , groupItem [ , ... ] ]

指定用于分组的列别名、位置或表达式。对于每个 groupItem,使用以下语法:

groupItem ::= { <column_alias> | <position> | <expr> }
Copy

其中:

  • column_alias 指定出现在查询块的 SELECT 列表中的列别名。

  • position 指定表达式在 SELECT 列表中的位置。

  • expr 指定当前作用域中表的任意表达式。

GROUP BY ALL

指定 SELECT 列表中不使用聚合函数的所有项都应用于分组。

有关示例,请参阅 按所有列分组

使用说明

  • GROUP BY 子句可以按名称或按位置引用投影子句中的表达式。如果 GROUP BY 子句按名称引用,则每个引用的解析方式如下:

    • 如果查询包含具有匹配列名的数据库对象(例如表或视图),则引用将解析为列名。

    • 否则,如果 SELECT 的投影子句包含具有匹配名称的表达式别名,则引用将解析为该别名。

    有关示例,请参阅 当列名和别名匹配时演示优先级

  • 如果所有 SELECT 项都使用聚合函数,则指定 GROUP BY ALL 等同于指定不带 GROUP BY 子句的语句。

    例如,以下语句仅包含使用聚合函数的 SELECT 项:

    SELECT SUM(amount)
      FROM mytable
      GROUP BY ALL;
    
    Copy

    上面的语句等同于不指定 GROUP by 子句:

    SELECT SUM(amount)
      FROM mytable;
    
    Copy

示例

以下各节提供了使用 GROUP BY 子句的示例:

请注意,各节中的示例使用您在“为示例设置数据”中设置的数据。

为示例设置数据

本节中的示例使用一个名为 sales 的表和一个名为 product 的表。要创建这些表并插入示例所需的数据,请执行以下语句:

CREATE TABLE sales (
  product_ID INTEGER,
  retail_price REAL,
  quantity INTEGER,
  city VARCHAR,
  state VARCHAR);

INSERT INTO sales (product_id, retail_price, quantity, city, state) VALUES
  (1, 2.00,  1, 'SF', 'CA'),
  (1, 2.00,  2, 'SJ', 'CA'),
  (2, 5.00,  4, 'SF', 'CA'),
  (2, 5.00,  8, 'SJ', 'CA'),
  (2, 5.00, 16, 'Miami', 'FL'),
  (2, 5.00, 32, 'Orlando', 'FL'),
  (2, 5.00, 64, 'SJ', 'PR');

CREATE TABLE products (
  product_ID INTEGER,
  wholesale_price REAL);
INSERT INTO products (product_ID, wholesale_price) VALUES (1, 1.00);
INSERT INTO products (product_ID, wholesale_price) VALUES (2, 2.00);
Copy

按一列分组

此示例显示每个产品的总收入,按 product_id 分组(即每个产品收到的总金额):

SELECT product_ID, SUM(retail_price * quantity) AS gross_revenue
  FROM sales
  GROUP BY product_ID;
Copy
+------------+---------------+
| PRODUCT_ID | GROSS_REVENUE |
+============+===============+
|          1 |          6    |
+------------+---------------+
|          2 |        620    |
+------------+---------------+

以下示例基于上一个示例,显示每个产品的净利润,按 product_id 分组:

SELECT p.product_ID, SUM((s.retail_price - p.wholesale_price) * s.quantity) AS profit
  FROM products AS p, sales AS s
  WHERE s.product_ID = p.product_ID
  GROUP BY p.product_ID;
Copy
+------------+--------+
| PRODUCT_ID | PROFIT |
+============+========+
|          1 |      3 |
+------------+--------+
|          2 |    372 |
+------------+--------+

按多列分组

下面的示例演示了如何按多个列进行分组:

SELECT state, city, SUM(retail_price * quantity) AS gross_revenue
  FROM sales
  GROUP BY state, city;
Copy
+-------+---------+---------------+
| STATE |   CITY  | GROSS REVENUE |
+=======+=========+===============+
|   CA  | SF      |            22 |
+-------+---------+---------------+
|   CA  | SJ      |            44 |
+-------+---------+---------------+
|   FL  | Miami   |            80 |
+-------+---------+---------------+
|   FL  | Orlando |           160 |
+-------+---------+---------------+
|   PR  | SJ      |           320 |
+-------+---------+---------------+

按所有列分组

以下示例等同于 按多列分组 中使用的示例。

SELECT state, city, SUM(retail_price * quantity) AS gross_revenue
  FROM sales
  GROUP BY ALL;
Copy
+-------+---------+---------------+
| STATE |   CITY  | GROSS REVENUE |
+=======+=========+===============+
|   CA  | SF      |            22 |
+-------+---------+---------------+
|   CA  | SJ      |            44 |
+-------+---------+---------------+
|   FL  | Miami   |            80 |
+-------+---------+---------------+
|   FL  | Orlando |           160 |
+-------+---------+---------------+
|   PR  | SJ      |           320 |
+-------+---------+---------------+

当列名和别名匹配时演示优先级

可以(但通常不要这么做)创建一个包含与列名称匹配的别名的查询:

SELECT x, some_expression AS x
  FROM ...
Copy

如果 GROUP BY 子句包含与列名和别名均匹配的名称,则 GROUP BY 子句将使用列名。下面的示例对此进行了演示。

创建表并插入行:

Create table employees (salary float, state varchar, employment_state varchar);
insert into employees (salary, state, employment_state) values
    (60000, 'California', 'Active'),
    (70000, 'California', 'On leave'),
    (80000, 'Oregon', 'Active');
Copy

下面的查询返回在职雇员的工资总和以及休假雇员的工资总和。

select sum(salary), ANY_VALUE(employment_state)
    from employees
    group by employment_state;
+-------------+-----------------------------+
| SUM(SALARY) | ANY_VALUE(EMPLOYMENT_STATE) |
|-------------+-----------------------------|
|      140000 | Active                      |
|       70000 | On leave                    |
+-------------+-----------------------------+
Copy

下面的查询使用别名 state,该别名与查询中表的列名匹配。当在 GROUP BY 中使用 state 时,Snowflake 将其解释为对列名的引用,而不是别名。因此,此查询返回加利福尼亚州雇员的工资总和以及俄勒冈州雇员的工资总和,但显示 employment_state 信息(例如“Active”),而不是州或省的名称。

select sum(salary), ANY_VALUE(employment_state) as state
    from employees
    group by state;
+-------------+--------+
| SUM(SALARY) | STATE  |
|-------------+--------|
|      130000 | Active |
|       80000 | Active |
+-------------+--------+
Copy
语言: 中文