HAVING 子句中使用聚合函数时,需要注意以下几个方面:

1. 必须与 GROUP BY 子句配合使用

HAVING 子句的主要作用是对分组后的结果进行筛选,因此它必须和 GROUP BY 子句一起使用。如果在没有 GROUP BY 子句的查询中使用 HAVING 子句,会导致语法错误。

示例(错误示范)

-- 此查询会报错,因为没有使用 GROUP BY 子句
SELECT SUM(salary)
FROM employees
HAVING SUM(salary) > 10000;

示例(正确示范)

-- 按部门分组,筛选出总工资大于 10000 的部门
SELECT department_id, SUM(salary)
FROM employees
GROUP BY department_id
HAVING SUM(salary) > 10000;

2. 聚合函数的计算逻辑

HAVING 子句中使用聚合函数时,要清楚聚合函数的计算逻辑。不同的聚合函数(如 SUMAVGCOUNTMAXMIN 等)有不同的计算方式,确保使用的聚合函数符合你的业务需求。

示例

-- 按部门分组,筛选出平均工资大于 5000 的部门
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id
HAVING AVG(salary) > 5000;

3. 数据类型和空值处理

  • 数据类型:聚合函数的结果数据类型要与 HAVING 子句中的比较条件的数据类型兼容。例如,如果聚合函数返回的是数值类型,那么比较条件也应该是数值类型。
  • 空值处理:聚合函数对空值的处理方式不同。例如,SUMAVGMAXMIN 会忽略空值,而 COUNT 可以选择是否包含空值。在使用聚合函数时,要考虑表中可能存在的空值对结果的影响。

示例

-- 按部门分组,筛选出员工数量(不包含空值)大于 5 的部门
SELECT department_id, COUNT(employee_id)
FROM employees
GROUP BY department_id
HAVING COUNT(employee_id) > 5;

4. 性能问题

HAVING 子句中使用复杂的聚合函数可能会影响查询性能。因为 HAVING 子句是在分组之后进行筛选的,如果数据量很大,分组和聚合操作会消耗较多的资源。可以考虑先使用 WHERE 子句过滤掉不必要的数据,减少分组和聚合的工作量。

示例

-- 先使用 WHERE 子句过滤掉工资小于 2000 的员工,再按部门分组筛选
SELECT department_id, SUM(salary)
FROM employees
WHERE salary > 2000
GROUP BY department_id
HAVING SUM(salary) > 10000;

5. 别名使用

如果在 SELECT 子句中为聚合函数指定了别名,在 HAVING 子句中不能直接使用该别名。不过,从 Oracle 12c 开始,支持在 HAVING 子句中使用 SELECT 列表中的别名。

示例(Oracle 12c 之前)

-- 不能在 HAVING 子句中使用别名 total_salary
SELECT department_id, SUM(salary) AS total_salary
FROM employees
GROUP BY department_id
HAVING SUM(salary) > 10000;

示例(Oracle 12c 及之后)

-- 可以在 HAVING 子句中使用别名 total_salary
SELECT department_id, SUM(salary) AS total_salary
FROM employees
GROUP BY department_id
HAVING total_salary > 10000;