作者:Timescale 团队
使用 PostgreSQL 或 TimescaleDB 时,您经常需要过滤查询结果以获得有意义的见解。虽然 WHERE
子句通常用于此目的,但它只能在聚合之前过滤行。为了在聚合之后过滤行组,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
在单个查询中同时使用 WHERE
和 HAVING
子句是很常见的。例如,如果我们只想查找 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 基础知识部分。