了解 PostgreSQL 中的 HAVING(附带示例)

Abstract shapes over a dark background.

作者:Timescale 团队

使用 PostgreSQL 或 TimescaleDB 时,您经常需要过滤查询结果以获得有意义的见解。虽然 WHERE 子句通常用于此目的,但它只能在聚合之前过滤行。为了在聚合之后过滤行组,PostgreSQL 提供了 HAVING 子句。

使用 PostgreSQL HAVING 子句

PostgreSQL 中的 HAVING 子句用于过滤 GROUP BY 操作的结果。它的工作原理类似于 WHERE 子句,但在聚合发生后应用。这使得它非常适合依赖于 聚合函数(如 SUM()COUNT()AVG() 等)的结果的条件。

语法

HAVING 子句的基本语法如下

SELECT column1, aggregate_function(column2)
FROM table
GROUP BY column1
HAVING condition;

示例表

让我们考虑一个名为 sales 的表,它具有以下结构和数据

CREATE TABLE sales (
    id SERIAL PRIMARY KEY,
    region VARCHAR(50),
    amount NUMERIC,
    sale_date DATE
);

INSERT INTO sales (region, amount, sale_date) VALUES
('North', 5000, '2023-01-15'),
('South', 3000, '2023-02-20'),
('North', 7000, '2023-03-10'),
('East', 2000, '2023-04-12'),
('West', 10000, '2023-05-05'),
('South', 12000, '2023-06-15'),
('East', 3000, '2023-07-18'),
('North', 15000, '2023-08-22'),
('West', 4000, '2023-09-30'),
('South', 5000, '2023-10-25');

实际例子

让我们深入了解一些示例,看看 HAVING 子句的实际应用。

示例 1:按 SUM 过滤组

假设我们要查找总销售额超过 10,000 美元的地区。我们可以将 HAVING 子句与 SUM() 函数一起使用

SELECT region, SUM(amount) AS total_sales
FROM sales
GROUP BY region
HAVING SUM(amount) > 10000;

结果

 region | total_sales
--------+-------------
 North  |       27000
 South  |       20000
 West   |       14000

此查询按 region 对行进行分组,计算每个地区的总销售额,并过滤总销售额超过 10,000 美元的组。

示例 2:将 HAVING 与 COUNT 一起使用

现在,假设我们要查找销售记录超过两 (2) 条的地区。我们可以将 COUNT() 函数与 HAVING 子句一起使用

SELECT region, COUNT(*) AS number_of_sales
FROM sales
GROUP BY region
HAVING COUNT(*) > 2;

结果

 region | number_of_sales
--------+-----------------
 North  |               3
 South  |               3

此查询计算每个地区的销售记录数量,并过滤组以仅包含销售额超过两笔的组。

示例 3:组合 WHERE 和 HAVING

在单个查询中同时使用 WHEREHAVING 子句是很常见的。例如,如果我们只想查找 2023 年总销售额超过 10,000 美元的地区,我们可以组合这两个子句

SELECT region, SUM(amount) AS total_sales
FROM sales
WHERE date_part('year', sale_date) = 2023
GROUP BY region
HAVING SUM(amount) > 10000;

结果

 region | total_sales
--------+-------------
 North  |       27000
 South  |       20000
 West   |       14000

在此示例中,WHERE 子句在分组发生之前过滤行以仅包含 2023 年的行。然后,HAVING 子句根据总销售额过滤组。

后续步骤

HAVING 子句是 PostgreSQL 中用于过滤分组数据的强大工具。它允许您对聚合数据应用条件,这在单独使用 WHERE 子句时是不可能的。通过理解和利用 HAVING 子句,您可以编写更精确、更有效的查询。 

要详细了解 PostgreSQL 子句和其他基础知识,请查看我们的 Postgres 基础知识部分