MySQL(27) 如何使用GROUP BY进行分组?

14 阅读3分钟

使用 GROUP BY 子句可以对查询结果进行分组,通常与聚合函数(如 COUNTSUMAVGMAXMIN)一起使用。GROUP BY 子句会将具有相同值的行归为一组,并对每组应用聚合函数。

基本语法

SELECT column1, column2, AGGREGATE_FUNCTION(column3)
FROM table_name
GROUP BY column1, column2;

示例数据库和表结构

假设我们有一个公司数据库,其中有两个表:employeesdepartments

-- 创建数据库
CREATE DATABASE company;

-- 选择数据库
USE company;

-- 创建表 departments
CREATE TABLE departments (
    dept_id INT AUTO_INCREMENT PRIMARY KEY,
    dept_name VARCHAR(100) NOT NULL
);

-- 创建表 employees
CREATE TABLE employees (
    emp_id INT AUTO_INCREMENT PRIMARY KEY,
    emp_name VARCHAR(100) NOT NULL,
    emp_position VARCHAR(100),
    emp_salary DECIMAL(10, 2),
    hire_date DATE,
    dept_id INT,
    FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);

-- 插入示例数据到 departments 表
INSERT INTO departments (dept_name)
VALUES 
('HR'),
('Engineering'),
('Marketing');

-- 插入示例数据到 employees 表
INSERT INTO employees (emp_name, emp_position, emp_salary, hire_date, dept_id)
VALUES 
('John Doe', 'Manager', 75000.00, '2023-10-01', 1),
('Jane Smith', 'Developer', 60000.00, '2023-09-01', 2),
('Alice Johnson', 'Analyst', 50000.00, '2023-08-01', 1),
('Bob Brown', 'Developer', 70000.00, '2023-07-01', 2),
('Charlie Brown', 'Tester', 55000.00, '2023-11-01', 3);

使用 GROUP BY 的示例

1. 按部门分组并计算每个部门的员工数量

SELECT dept_id, COUNT(*) AS num_employees
FROM employees
GROUP BY dept_id;

结果:

dept_id | num_employees
--------|---------------
1       | 2
2       | 2
3       | 1

2. 按职位分组并计算每个职位的平均薪水

SELECT emp_position, AVG(emp_salary) AS avg_salary
FROM employees
GROUP BY emp_position;

结果:

emp_position | avg_salary
-------------|------------
Analyst      | 50000.00
Developer    | 65000.00
Manager      | 75000.00
Tester       | 55000.00

3. 按部门分组并计算每个部门的总薪水

SELECT dept_id, SUM(emp_salary) AS total_salary
FROM employees
GROUP BY dept_id;

结果:

dept_id | total_salary
--------|--------------
1       | 125000.00
2       | 130000.00
3       | 55000.00

使用 GROUP BY 和 HAVING 子句

HAVING 子句用于对分组后的结果进行过滤,与 WHERE 子句类似,但 WHERE 子句是在分组前进行过滤的,而 HAVING 子句是在分组后进行过滤的。

4. 按部门分组并计算每个部门的员工数量,仅显示员工数量大于1的部门

SELECT dept_id, COUNT(*) AS num_employees
FROM employees
GROUP BY dept_id
HAVING COUNT(*) > 1;

结果:

dept_id | num_employees
--------|---------------
1       | 2
2       | 2

5. 按职位分组并计算每个职位的平均薪水,仅显示平均薪水超过60000的职位

SELECT emp_position, AVG(emp_salary) AS avg_salary
FROM employees
GROUP BY emp_position
HAVING AVG(emp_salary) > 60000;

结果:

emp_position | avg_salary
-------------|------------
Developer    | 65000.00
Manager      | 75000.00

多列分组

6. 按部门和职位分组,计算每组的员工数量

SELECT dept_id, emp_position, COUNT(*) AS num_employees
FROM employees
GROUP BY dept_id, emp_position;

结果:

dept_id | emp_position | num_employees
--------|--------------|---------------
1       | Manager      | 1
1       | Analyst      | 1
2       | Developer    | 2
3       | Tester       | 1

结合 JOIN 和 GROUP BY

7. 按部门名称分组,计算每个部门的员工数量

SELECT d.dept_name, COUNT(e.emp_id) AS num_employees
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id
GROUP BY d.dept_name;

结果:

dept_name   | num_employees
------------|---------------
HR          | 2
Engineering | 2
Marketing   | 1

8. 按部门名称分组,计算每个部门的总薪水

SELECT d.dept_name, SUM(e.emp_salary) AS total_salary
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id
GROUP BY d.dept_name;

结果:

dept_name   | total_salary
------------|--------------
HR          | 125000.00
Engineering | 130000.00
Marketing   | 55000.00

小结

通过使用 GROUP BY 子句,您可以对查询结果进行分组,并且可以结合聚合函数来计算各组的数据统计信息。使用 HAVING 子句可以对分组后的结果进行进一步的过滤,GROUP BY 子句也可以与 JOIN 结合使用,以实现更复杂的数据查询和分析。上述示例展示了不同情况下如何使用 GROUP BY 子句进行分组和计算,这在数据分析和报告中非常有用。