【SQL函数入门】掌握SUM, AVG, MAX, MIN,成为数据聚合达人!
在制作网站销售报告时,“这个月的总销售额是多少?”、“商品的平均单价是多少?”、“卖得最贵的商品是什么?”这类信息是必不可少的。当你想将数据库中积累的零散数据汇总成一个有意义的数值时——能发挥巨大作用的,便是SQL的聚合函数。
聚合函数,是指接收跨越多行的数据作为输入,并返回单个值作为其聚合结果的函数。打个比方,就像把许多写有数字的纸张读入计算器,然后输出“总和”或“平均值”这样的一个答案。
本文将通过大量可即拷即用的代码,深入浅出地讲解在众多聚合函数中使用频率最高、作为数据分析基础的“四大天王”——SUM(), AVG(), MAX(), MIN() 的用法。掌握这些函数并与`GROUP BY`结合使用,你的数据分析能力将得到飞跃性的提升!
准备工作:创建用于聚合的销售数据
要尝试聚合函数,首先需要有可供聚合的数值数据。这次,我们将创建一个模拟电商网站销售历史的sales表。包含多个类别以及不同价格和数量的数据,可以让我们更清晰地了解每个函数的作用。
-- 如果sales表已存在,则删除(以便重复测试)
DROP TABLE IF EXISTS sales;
-- 创建一个新的sales表
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
product_name TEXT NOT NULL,
category TEXT NOT NULL,
price INTEGER NOT NULL,
quantity INTEGER NOT NULL,
sale_date DATE NOT NULL
);
-- 插入初始数据
INSERT INTO sales (id, product_name, category, price, quantity, sale_date) VALUES
(1, '神奇圆珠笔', '文具', 150, 10, '2025-07-01'),
(2, '魔法笔记本', '文具', 300, 5, '2025-07-01'),
(3, '终极电饭煲', '家电', 25000, 2, '2025-07-02'),
(4, '奇迹苹果', '食品', 500, 20, '2025-07-03'),
(5, 'USB-C集线器', '电脑外设', 4000, 3, '2025-07-03'),
(6, '传统毛笔', '文具', 1200, 8, '2025-07-04'),
(7, '高级巧克力', '食品', 3500, 5, '2025-07-05'),
(8, '神奇圆珠笔', '文具', 150, 15, '2025-07-05');
这样,从各种角度聚合数据的准备工作就完成了。
【求和】使用`SUM()`函数计算合计值
SUM()函数用于计算指定数值列的总和。在商业场景中,如“销售总额”、“总库存数”、“总积分”等需要了解“总计”的情况非常多,是-最基本的聚合函数之一。
在SUM()的括号内,指定你想要合计的列名。也可以对列与列之间计算的结果进行合计。
场景:“所有销售的总额(总收入)是多少?”
在这种情况下,我们计算每条记录的“价格(price) × 数量(quantity)”,然后将所有结果相加。
SELECT SUM(price * quantity) AS total_revenue FROM sales;
执行结果:
total_revenue
-------------
102850
使用AS total_revenue为结果列赋予一个意为“总收入”的、易于理解的名称,这也是一个重点。
【求平均】使用`AVG()`函数计算平均值
AVG()(Average的缩写)函数用于计算指定数值列的平均值。它有助于把握数据的整体趋势,如“平均年龄”、“平均得分”、“平均单价”等。
场景:“售出商品的平均单价是多少?”
SELECT AVG(price) AS average_price FROM sales;
执行结果:
average_price
-------------
5562.5
需要注意的是,如果计算的列中包含`NULL`值,`SUM()`和`AVG()`在聚合时会忽略这些行。这有时可能会导致意想不到的结果,所以请记住这一点。
【最大/最小】使用`MAX()`和`MIN()`函数查找最大值和最小值
MAX()(Maximum)和MIN()(Minimum)顾名思义,是用于获取列中最大值和最小值的函数。将这两个函数作为一对来学习会更有效率。
`MAX()`函数:找到最大值
场景:“单次交易中金额最高的销售额是多少?”
SELECT MAX(price * quantity) AS highest_sale FROM sales;
执行结果:
highest_sale
------------
50000
这是ID为3的“终极电饭煲”(25,000 × 2)的销售额。
`MIN()`函数:找到最小值
场景:“在售出的商品中,单价最低的是多少?”
SELECT MIN(price) AS cheapest_price FROM sales;
执行结果:
cheapest_price
--------------
150
`MAX()`和`MIN()`不仅可以用于数值,还可以用于日期(最新/最早的日期)和字符串(字典序的最后/最前),是非常通用的函数。
【最强组合】`GROUP BY`子句与聚合函数
这四个聚合函数的真正价值,在与`GROUP BY`子句结合使用时才能得到最大发挥。使用`GROUP BY`可以按特定列的值将数据分组,然后对**每个分组**分别应用聚合函数。
这样就可以进行更实用、更详细的分析,例如“各品类的销售总额”或“各商品的平均销售数量”。
场景:“按商品类别,汇总总销售额、平均单价和总销售数量。”
SELECT
category,
SUM(price * quantity) AS total_revenue,
AVG(price) AS average_price,
SUM(quantity) AS total_quantity_sold
FROM
sales
GROUP BY
category;
执行结果:
category | total_revenue | average_price | total_quantity_sold
---------|---------------|---------------|---------------------
电脑外设 | 12000 | 4000 | 3
家电 | 50000 | 25000 | 2
文具 | 13350 | 550 | 33
食品 | 27500 | 2000 | 25
通过这一个查询,每个类别的详细销售业绩一目了然。像这样,通过将聚合函数与`GROUP BY`相结合,可以从原始的数字列表中提取出对业务有用的“洞见”。
【体验环节】在浏览器中运行SQL,体验数据聚合!
现在,是时候把知识变成技能了!将下面的HTML代码完整复制,保存为sql_aggregate_test.html之类的文件名,然后在浏览器中打开它。你专属的SQL执行环境将会启动,并且本文中使用的sales表已经为你准备好了。
试着把`SUM`改成`AVG`,或者在`GROUP BY`中添加不同的列,自由地进行尝试,亲眼见证数据是如何被聚合,并转变为有意义的信息的!
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQL聚合函数 在线执行环境</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #2980b9; }
textarea { width: 100%; height: 220px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #3498db; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
button:hover { background-color: #2980b9; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; }
#error-message { color: #e74c3c; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>来试试SQL吧!</h1>
<p>在下方的文本框中输入SQL语句,然后点击“执行”按钮。来试试各种聚合操作吧!</p>
<textarea id="sql-input">-- 按商品名称分组,计算每种商品的总销售额和总销售数量
SELECT
product_name,
SUM(price * quantity) AS total_revenue,
SUM(quantity) AS total_quantity
FROM
sales
GROUP BY
product_name
ORDER BY
total_revenue DESC;
</textarea>
<button id="execute-btn">执行</button>
<div id="result-container">
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = '数据库准备中...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
const setupSql = `
DROP TABLE IF EXISTS sales;
CREATE TABLE sales (id INTEGER PRIMARY KEY, product_name TEXT NOT NULL, category TEXT NOT NULL, price INTEGER NOT NULL, quantity INTEGER NOT NULL, sale_date DATE NOT NULL);
INSERT INTO sales (id, product_name, category, price, quantity, sale_date) VALUES
(1, '神奇圆珠笔', '文具', 150, 10, '2025-07-01'),
(2, '魔法笔记本', '文具', 300, 5, '2025-07-01'),
(3, '终极电饭煲', '家电', 25000, 2, '2025-07-02'),
(4, '奇迹苹果', '食品', 500, 20, '2025-07-03'),
(5, 'USB-C集线器', '电脑外设', 4000, 3, '2025-07-03'),
(6, '传统毛笔', '文具', 1200, 8, '2025-07-04'),
(7, '高级巧克力', '食品', 3500, 5, '2025-07-05'),
(8, '神奇圆珠笔', '文具', 150, 15, '2025-07-05');
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = '执行';
resultOutput.innerHTML = '<p>准备就绪!请随意尝试你自己的SQL查询。</p>';
} catch (err) {
errorMsg.textContent = '数据库初始化失败:' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const results = db.exec(sql);
if (results.length === 0) {
resultOutput.innerHTML = '<p>查询成功执行,但没有返回结果集。</p>';
return;
}
results.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue.toLocaleString('zh-CN');
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
} catch (err) {
errorMsg.textContent = 'SQL错误:' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
总结
这次,我们学习了数据分析基础中的四个聚合函数:`SUM()`, `AVG()`, `MAX()`, `MIN()`。
- `SUM()`: 计算数值的总和。用于“总销售额”、“总数量”等。
- `AVG()`: 计算数值的平均值。用于“平均单价”、“平均得分”等。
- `MAX()`: 找到数值、日期等之中的最大值。用于“最高价格”、“最新日期”等。
- `MIN()`: 找到数值、日期等之中的最小值。用于“最低价格”、“最早日期”等。
- 最强武器 `GROUP BY`: 这些聚合函数与
GROUP BY子句结合使用时,可以实现分组聚合,从而发挥其真正价值。 - 注意事项: 这些聚合函数在计算时会忽略`NULL`值。
这些聚合函数不仅是检索数据的工具,更是从数据中获得有意义的洞见的****第一步。无论是商业决策还是网站改进,它们都是Web开发者手中非常强大的武器。请务必熟练使用这些函数,感受与数据对话的乐趣!