以古论今 發表於 2025-5-15 10:48:56

详解SQL中不能轻视的 HAVING 子句

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">HAVING 子句概述</a></li><li><a href="#_label1">1. HAVING 的基本语法</a></li><li><a href="#_label2">2. WHERE 和 HAVING 的区别</a></li><li><a href="#_label3">HAVING 子句的应用实例</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_0">案例 1:计算每个部门的员工数,并筛选员工数大于 3 的部门</a></li><li><a href="#_lab2_3_1">案例 2:筛选平均薪资高于 5000 的部门</a></li><li><a href="#_lab2_3_2">案例 3:同时使用 WHERE 和 HAVING</a></li></ul><li><a href="#_label4">HAVING 子句的高级用法</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_3">1. 使用多重条件筛选</a></li><li><a href="#_lab2_4_4">2. 使用 HAVING 进行范围筛选</a></li><li><a href="#_lab2_4_5">3. 结合 ORDER BY 进行排序</a></li></ul><li><a href="#_label5">HAVING 子句的优化策略</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">总结</a></li><ul class="second_class_ul"></ul></ul></div><p>在本文中,我们将深入解析 HAVING 的功能,了解它的用法,以及它和 WHERE 子句的区别。通过许多实际案例,我们将完整地分析 HAVING 在 SQL 中的实际应用。</p>
<p class="maodian"><a name="_label0"></a></p><h2>HAVING 子句概述</h2>
<p><code>HAVING</code>&nbsp;子句专门用于&nbsp;对聚合数据进行过滤,即它用于&nbsp;<code>GROUP BY</code>&nbsp;语句的结果集。在执行 SQL 查询时,我们通常先用&nbsp;<code>WHERE</code>&nbsp;过滤原始数据,然后用&nbsp;<code>HAVING</code>&nbsp;对分组后的数据进行进一步筛选。</p>
<p class="maodian"><a name="_label1"></a></p><h2>1. HAVING 的基本语法</h2>
<div class="jb51code"><pre class="brush:sql;">SELECT 列名, 聚合函数
FROM 表名
GROUP BY 列名
HAVING 条件;</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>2. WHERE 和 HAVING 的区别</h2>
<table><tbody><tr><th>对比项</th><th>WHERE 子句</th><th>HAVING 子句</th></tr><tr><td>作用范围</td><td>作用于&nbsp;单行数据</td><td>作用于&nbsp;聚合后的数据</td></tr><tr><td>作用对象</td><td>普通列</td><td>聚合函数 (SUM、AVG、COUNT 等)</td></tr><tr><td>使用场景</td><td>过滤原始数据</td><td>过滤聚合后的数据</td></tr><tr><td>语法位置</td><td>在&nbsp;<code>GROUP BY</code>&nbsp;之前</td><td>在&nbsp;<code>GROUP BY</code>&nbsp;之后</td></tr><tr><td>计算影响</td><td>影响分组前的数据集大小</td><td>影响分组后的数据集大小</td></tr></tbody></table>
<p>在 SQL 查询优化中,推荐&nbsp;尽可能使用&nbsp;<code>WHERE</code>&nbsp;进行初步筛选,以减少&nbsp;<code>GROUP BY</code>&nbsp;需要处理的数据量,从而提升查询效率。</p>
<p class="maodian"><a name="_label3"></a></p><h2>HAVING 子句的应用实例</h2>
<p class="maodian"><a name="_lab2_3_0"></a></p><h3>案例 1:计算每个部门的员工数,并筛选员工数大于 3 的部门</h3>
<div class="jb51code"><pre class="brush:sql;">SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) &gt; 3;</pre></div>
<p>📌&nbsp;解析:</p>
<ul><li><p><code>GROUP BY department</code>&nbsp;按部门分组。</p></li><li><p><code>COUNT(*)</code>&nbsp;计算每个部门的员工数量。</p></li><li><p><code>HAVING COUNT(*) &gt; 3</code>&nbsp;只保留&nbsp;员工数量大于 3 的部门。</p></li></ul>
<p class="maodian"><a name="_lab2_3_1"></a></p><h3>案例 2:筛选平均薪资高于 5000 的部门</h3>
<div class="jb51code"><pre class="brush:sql;">SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) &gt; 5000;</pre></div>
<p>📌&nbsp;解析:</p>
<ul><li><p>计算&nbsp;<code>department</code>&nbsp;组内的平均薪资。</p></li><li><p><code>HAVING</code>&nbsp;过滤掉&nbsp;平均薪资低于 5000 的部门。</p></li></ul>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>案例 3:同时使用 WHERE 和 HAVING</h3>
<div class="jb51code"><pre class="brush:sql;">SELECT department, SUM(salary) AS total_salary
FROM employees
WHERE salary &gt; 3000
GROUP BY department
HAVING SUM(salary) &gt; 20000;</pre></div>
<p>📌&nbsp;解析:</p>
<ul><li><p><code>WHERE salary &gt; 3000</code>&nbsp;先筛选&nbsp;工资高于 3000 的员工。</p></li><li><p><code>GROUP BY department</code>&nbsp;按部门分组。</p></li><li><p><code>HAVING SUM(salary) &gt; 20000</code>&nbsp;只保留&nbsp;薪资总和大于 20000 的部门。</p></li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>HAVING 子句的高级用法</h2>
<p class="maodian"><a name="_lab2_4_3"></a></p><h3>1. 使用多重条件筛选</h3>
<div class="jb51code"><pre class="brush:sql;">SELECT department, COUNT(*) AS emp_count, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING COUNT(*) &gt; 5 AND AVG(salary) &gt; 6000;</pre></div>
<p>📌&nbsp;解析:</p>
<ul><li><p><code>HAVING</code>&nbsp;支持逻辑运算符&nbsp;<code>AND</code>、<code>OR</code>&nbsp;组合多个条件。</p></li><li><p>过滤掉&nbsp;员工数少于 5 或者平均薪资低于 6000 的部门。</p></li></ul>
<p class="maodian"><a name="_lab2_4_4"></a></p><h3>2. 使用 HAVING 进行范围筛选</h3>
<div class="jb51code"><pre class="brush:sql;">SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) BETWEEN 10000 AND 50000;</pre></div>
<p>📌&nbsp;解析:</p>
<ul><li><p><code>HAVING SUM(salary) BETWEEN 10000 AND 50000</code>&nbsp;过滤&nbsp;薪资总和在 10000 到 50000 之间的部门。</p></li></ul>
<p class="maodian"><a name="_lab2_4_5"></a></p><h3>3. 结合 ORDER BY 进行排序</h3>
<div class="jb51code"><pre class="brush:sql;">SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) &gt; 3
ORDER BY COUNT(*) DESC;</pre></div>
<p>📌&nbsp;解析:</p>
<ul><li><p><code>ORDER BY COUNT(*) DESC</code>&nbsp;按&nbsp;员工数降序排列,以便快速查看最大部门。</p></li></ul>
<p class="maodian"><a name="_label5"></a></p><h2>HAVING 子句的优化策略</h2>
<ul><li><p>尽量使用 WHERE 进行初步筛选,减少数据规模,提高&nbsp;<code>GROUP BY</code>&nbsp;计算效率。</p></li><li><p>避免在 HAVING 语句中进行复杂计算,可以将计算结果存入临时表,提高查询性能。</p></li><li><p>使用索引优化分组字段,如果&nbsp;<code>GROUP BY</code>&nbsp;作用在大表的字段上,可以考虑创建索引,以提升查询速度。</p></li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>总结</h2>
<ul><li><p><code>HAVING</code>&nbsp;主要用于&nbsp;对聚合结果进行筛选,而&nbsp;<code>WHERE</code>&nbsp;用于&nbsp;单行数据的筛选。</p></li><li><p>在 SQL 查询优化时,推荐&nbsp;优先使用&nbsp;<code>WHERE</code>&nbsp;过滤原始数据,然后在&nbsp;<code>HAVING</code>&nbsp;里进行聚合数据筛选。</p></li><li><p><code>HAVING</code>&nbsp;适用于 COUNT、SUM、AVG、MAX、MIN 等聚合函数的筛选,配合&nbsp;<code>ORDER BY</code>&nbsp;可以更方便地分析数据。</p></li></ul>
<p>通过合理使用&nbsp;<code>HAVING</code>,可以有效优化 SQL 查询,提高数据库操作的效率。</p>
頁: [1]
查看完整版本: 详解SQL中不能轻视的 HAVING 子句