首页 > 数据库 > SQL > 正文

sql如何使用group by进行数据分组统计 sqlgroup by分组统计的操作教程

看不見的法師
发布: 2025-08-16 13:58:01
原创
941人浏览过

group by语句用于将具有相同值的行分组并应用聚合函数进行统计分析,其基本语法为select列名 from表名 where条件 group by分组列 order by排序列;它支持单列或多列分组,并可结合having子句过滤分组结果,where子句在group by前执行以减少数据量,select中非聚合列必须出现在group by中,null值在分组时被视为相等并归为一组,可通过coalesce、where或case处理null值;与distinct相比,group by用于分组聚合而distinct仅去重,前者可直接使用聚合函数,后者性能通常更优;优化group by性能的方法包括创建索引(尤其是覆盖索引)、避免select *、使用where提前过滤、利用临时表或物化视图、重写查询使用窗口函数、简化having条件以及调整数据库配置或硬件资源,具体策略需根据查询场景选择并结合性能分析工具定位瓶颈。

sql如何使用group by进行数据分组统计 sqlgroup by分组统计的操作教程

SQL中的

GROUP BY
登录后复制
语句用于将具有相同值的行分组到一起,然后可以对每个组应用聚合函数(如
COUNT
登录后复制
SUM
登录后复制
AVG
登录后复制
MIN
登录后复制
MAX
登录后复制
)进行统计分析。它允许你基于一个或多个列的值来汇总数据,从而获得更高级别的视图。

SQL

GROUP BY
登录后复制
分组统计的操作教程

GROUP BY
登录后复制
语句的基本语法如下:

SELECT column1, column2, ..., aggregate_function(column_n)
FROM table_name
WHERE condition
GROUP BY column1, column2, ...
ORDER BY column1, column2, ...;
登录后复制
  • SELECT
    登录后复制
    :指定要选择的列,包括分组列和聚合函数的结果。
  • FROM
    登录后复制
    :指定要查询的表。
  • WHERE
    登录后复制
    :可选,用于过滤行。
  • GROUP BY
    登录后复制
    :指定用于分组的列。
  • ORDER BY
    登录后复制
    :可选,用于对结果进行排序。

示例:统计每个部门的员工数量

假设有一个名为

employees
登录后复制
的表,包含以下列:
id
登录后复制
name
登录后复制
department
登录后复制
salary
登录后复制

要统计每个部门的员工数量,可以使用以下SQL语句:

SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department;
登录后复制

这条语句会按照

department
登录后复制
列进行分组,然后使用
COUNT(*)
登录后复制
函数计算每个部门的员工数量。
AS employee_count
登录后复制
用于给
COUNT(*)
登录后复制
的结果起一个别名,方便引用。

示例:统计每个部门的平均工资

类似地,要统计每个部门的平均工资,可以使用以下SQL语句:

SELECT department, AVG(salary) AS average_salary
FROM employees
GROUP BY department;
登录后复制

这条语句会按照

department
登录后复制
列进行分组,然后使用
AVG(salary)
登录后复制
函数计算每个部门的平均工资。

多个列进行分组

GROUP BY
登录后复制
可以同时使用多个列进行分组。例如,要统计每个部门每个职位的员工数量,可以使用以下SQL语句:

SELECT department, position, COUNT(*) AS employee_count
FROM employees
GROUP BY department, position;
登录后复制

这条语句会先按照

department
登录后复制
列进行分组,然后在每个部门内再按照
position
登录后复制
列进行分组。

HAVING
登录后复制
子句

HAVING
登录后复制
子句用于过滤分组后的结果。它类似于
WHERE
登录后复制
子句,但是
WHERE
登录后复制
子句用于过滤行,而
HAVING
登录后复制
子句用于过滤组。

例如,要统计员工数量超过5个的部门,可以使用以下SQL语句:

SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
登录后复制

这条语句会先按照

department
登录后复制
列进行分组,然后使用
COUNT(*)
登录后复制
函数计算每个部门的员工数量,最后使用
HAVING COUNT(*) > 5
登录后复制
过滤掉员工数量小于等于5的部门。

注意事项

  • SELECT
    登录后复制
    列表中除了聚合函数之外的列,都必须出现在
    GROUP BY
    登录后复制
    子句中。
  • GROUP BY
    登录后复制
    子句中可以使用别名,但是不能使用聚合函数。
  • HAVING
    登录后复制
    子句中可以使用聚合函数。
  • GROUP BY
    登录后复制
    子句的性能可能会受到数据量和索引的影响。

GROUP BY
登录后复制
WHERE
登录后复制
子句的执行顺序

WHERE
登录后复制
子句在
GROUP BY
登录后复制
子句之前执行。这意味着
WHERE
登录后复制
子句会先过滤行,然后再进行分组。

示例:统计工资大于50000的员工所在的部门的平均工资

SELECT department, AVG(salary) AS average_salary
FROM employees
WHERE salary > 50000
GROUP BY department;
登录后复制

这条语句会先使用

WHERE salary > 50000
登录后复制
过滤掉工资小于等于50000的员工,然后再按照
department
登录后复制
列进行分组,最后计算每个部门的平均工资。

总结

GROUP BY
登录后复制
语句是SQL中非常强大的工具,可以用于对数据进行分组和统计分析。掌握
GROUP BY
登录后复制
语句的用法,可以帮助你更好地理解和分析数据。

如何优化SQL GROUP BY查询的性能?

优化

GROUP BY
登录后复制
查询的性能通常涉及几个关键策略,包括索引优化、查询重写和硬件资源调整。

  1. 索引优化: 确保

    GROUP BY
    登录后复制
    子句中使用的列上有合适的索引。 如果没有索引,数据库可能需要执行全表扫描,这会显著降低查询速度。 组合索引(Composite Index)可能更有效,特别是当
    GROUP BY
    登录后复制
    子句包含多个列时。

    -- 创建索引的示例
    CREATE INDEX idx_department ON employees (department);
    CREATE INDEX idx_department_position ON employees (department, position);
    登录后复制
  2. *避免SELECT :* 只选择需要的列。选择所有列(`SELECT `)会增加数据传输量,从而降低性能。

    -- 优化前
    SELECT * FROM employees GROUP BY department;
    
    -- 优化后
    SELECT department, COUNT(*) FROM employees GROUP BY department;
    登录后复制
  3. 使用覆盖索引: 覆盖索引是指索引包含了查询所需的所有列,这样数据库就可以直接从索引中获取数据,而不需要访问表。

    -- 创建覆盖索引的示例
    CREATE INDEX idx_department_salary ON employees (department, salary);
    
    -- 查询可以使用覆盖索引
    SELECT department, AVG(salary) FROM employees GROUP BY department;
    登录后复制
  4. WHERE子句过滤:

    GROUP BY
    登录后复制
    之前使用
    WHERE
    登录后复制
    子句过滤数据,可以减少需要分组的数据量。

    -- 优化前
    SELECT department, COUNT(*) FROM employees GROUP BY department HAVING salary > 50000;
    
    -- 优化后
    SELECT department, COUNT(*) FROM employees WHERE salary > 50000 GROUP BY department;
    登录后复制
  5. 使用临时表或物化视图: 对于复杂的

    GROUP BY
    登录后复制
    查询,可以考虑使用临时表或物化视图来预先计算结果,从而提高查询速度。

    -- 创建临时表的示例
    CREATE TEMPORARY TABLE temp_employee_counts AS
    SELECT department, COUNT(*) AS employee_count FROM employees GROUP BY department;
    
    -- 查询临时表
    SELECT * FROM temp_employee_counts;
    登录后复制
  6. 查询重写: 某些查询可以通过重写来避免使用

    GROUP BY
    登录后复制
    。 例如,可以使用窗口函数来替代
    GROUP BY
    登录后复制

    -- 使用窗口函数替代GROUP BY的示例
    SELECT department, COUNT(*) OVER (PARTITION BY department) AS employee_count FROM employees;
    登录后复制
  7. 数据库配置: 调整数据库的配置参数,例如增加缓冲区大小、调整查询优化器等,可以提高查询性能。

    美图设计室
    美图设计室

    5分钟在线高效完成平面设计,AI帮你做设计

    美图设计室 29
    查看详情 美图设计室
  8. 硬件升级: 如果以上优化方法都无法满足需求,可以考虑升级硬件,例如增加内存、使用更快的磁盘等。

  9. 避免在

    HAVING
    登录后复制
    子句中使用复杂的表达式: 尽量简化
    HAVING
    登录后复制
    子句中的条件,或者将复杂的条件移到
    WHERE
    登录后复制
    子句中。

    -- 优化前
    SELECT department, AVG(salary) FROM employees GROUP BY department HAVING AVG(salary) > (SELECT AVG(salary) FROM employees);
    
    -- 优化后 (可能需要具体情况具体分析)
    SELECT department, AVG(salary) FROM employees GROUP BY department HAVING AVG(salary) > 60000; -- 假设平均工资是60000
    登录后复制
  10. 使用近似聚合函数: 对于某些场景,可以使用近似聚合函数(例如

    APPROX_COUNT_DISTINCT
    登录后复制
    )来提高查询速度,但可能会损失一定的精度。

选择哪种优化策略取决于具体的查询和数据。 建议使用数据库的性能分析工具来确定查询瓶颈,并选择最合适的优化方法。

GROUP BY 如何处理 NULL 值?

GROUP BY
登录后复制
在处理
NULL
登录后复制
值时,会将所有
NULL
登录后复制
值视为相等并放在同一个组中。这意味着,如果
GROUP BY
登录后复制
子句中包含的列有
NULL
登录后复制
值,那么所有
NULL
登录后复制
值的行会被分到同一个组。

示例:

假设有一个名为

products
登录后复制
的表,包含以下列:
id
登录后复制
name
登录后复制
category
登录后复制
price
登录后复制
category
登录后复制
列允许
NULL
登录后复制
值。

-- 创建表并插入数据
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    category VARCHAR(255),
    price DECIMAL(10, 2)
);

INSERT INTO products (id, name, category, price) VALUES
(1, 'Product A', 'Category 1', 10.00),
(2, 'Product B', 'Category 2', 20.00),
(3, 'Product C', 'Category 1', 15.00),
(4, 'Product D', NULL, 25.00),
(5, 'Product E', NULL, 30.00);
登录后复制

现在,我们使用

GROUP BY
登录后复制
子句按照
category
登录后复制
列进行分组,并计算每个类别的产品数量:

SELECT category, COUNT(*) AS product_count
FROM products
GROUP BY category;
登录后复制

查询结果如下:

category product_count
Category 1 2
Category 2 1
NULL 2

可以看到,

category
登录后复制
NULL
登录后复制
的两个产品被分到了同一个组,
product_count
登录后复制
为2。

处理NULL值的技巧

  1. 使用

    COALESCE
    登录后复制
    函数: 可以使用
    COALESCE
    登录后复制
    函数将
    NULL
    登录后复制
    值替换为其他值,从而避免
    NULL
    登录后复制
    值被分到同一个组。

    SELECT COALESCE(category, 'Unknown') AS category, COUNT(*) AS product_count
    FROM products
    GROUP BY COALESCE(category, 'Unknown');
    登录后复制

    这条语句会将

    category
    登录后复制
    NULL
    登录后复制
    的值替换为
    'Unknown'
    登录后复制
    ,然后按照替换后的值进行分组。

  2. 使用

    WHERE
    登录后复制
    子句过滤
    NULL
    登录后复制
    值:
    可以使用
    WHERE
    登录后复制
    子句过滤掉
    NULL
    登录后复制
    值,从而避免
    NULL
    登录后复制
    值参与分组。

    SELECT category, COUNT(*) AS product_count
    FROM products
    WHERE category IS NOT NULL
    GROUP BY category;
    登录后复制

    这条语句会过滤掉

    category
    登录后复制
    NULL
    登录后复制
    的产品,然后按照
    category
    登录后复制
    列进行分组。

  3. 使用

    CASE
    登录后复制
    语句: 可以使用
    CASE
    登录后复制
    语句根据
    NULL
    登录后复制
    值进行不同的处理。

    SELECT
        CASE
            WHEN category IS NULL THEN 'No Category'
            ELSE category
        END AS category_name,
        COUNT(*) AS product_count
    FROM products
    GROUP BY category_name;
    登录后复制

    这条语句会创建一个新的列

    category_name
    登录后复制
    ,如果
    category
    登录后复制
    NULL
    登录后复制
    ,则
    category_name
    登录后复制
    'No Category'
    登录后复制
    ,否则
    category_name
    登录后复制
    category
    登录后复制
    的值。 然后按照
    category_name
    登录后复制
    列进行分组。

选择哪种处理

NULL
登录后复制
值的技巧取决于具体的业务需求。 需要根据实际情况选择最合适的处理方式。

GROUP BY 和 DISTINCT 的区别是什么?

GROUP BY
登录后复制
DISTINCT
登录后复制
都可以用来去除重复的行,但它们的目的和用法有所不同。

DISTINCT:

  • 目的: 用于从结果集中去除重复的行,只返回唯一的行。
  • 用法:
    SELECT DISTINCT column1, column2, ... FROM table_name;
    登录后复制
  • 结果: 返回指定列的唯一组合。
  • 聚合函数: 不能直接与聚合函数一起使用。 如果要使用聚合函数,需要使用子查询。
  • 性能: 通常比
    GROUP BY
    登录后复制
    快,因为它只需要去除重复的行,而不需要进行分组和聚合。

GROUP BY:

  • 目的: 用于将具有相同值的行分组到一起,然后可以对每个组应用聚合函数进行统计分析。
  • 用法:
    SELECT column1, column2, ..., aggregate_function(column_n) FROM table_name GROUP BY column1, column2, ...;
    登录后复制
  • 结果: 返回每个组的聚合结果。
  • 聚合函数: 可以直接与聚合函数一起使用。
  • 性能: 在大数据量的情况下,性能可能比
    DISTINCT
    登录后复制
    差,因为它需要进行分组和聚合。

区别总结:

特性 DISTINCT GROUP BY
目的 去除重复行 分组和聚合
用法 @@######@@ @@######@@
结果 唯一行的集合 每个组的聚合结果
聚合函数 不能直接使用 可以直接使用
性能 通常更快 可能较慢,取决于数据量和复杂度

示例:

假设有一个名为

SELECT DISTINCT column1, column2, ...
登录后复制
的表,包含以下列:
SELECT column1, aggregate_function(column2) FROM ... GROUP BY column1
登录后复制
orders
登录后复制
order_id
登录后复制

使用DISTINCT获取唯一的customer_id:

customer_id
登录后复制

这条语句会返回所有唯一的

order_date
登录后复制

使用GROUP BY统计每个customer_id的订单数量:

SELECT DISTINCT customer_id FROM orders;
登录后复制

这条语句会返回每个

customer_id
登录后复制
及其对应的订单数量。

何时使用DISTINCT vs GROUP BY:

  • 如果只需要去除重复的行,而不需要进行聚合,则使用
    SELECT customer_id, COUNT(*) AS order_count FROM orders GROUP BY customer_id;
    登录后复制
  • 如果需要对数据进行分组和聚合,则使用
    customer_id
    登录后复制

在某些情况下,

DISTINCT
登录后复制
GROUP BY
登录后复制
可以实现相同的结果,但是它们的执行方式不同。 例如,以下两个语句可以实现相同的结果:

DISTINCT
登录后复制

但是,

GROUP BY
登录后复制
通常比
SELECT DISTINCT customer_id FROM orders;

SELECT customer_id FROM orders GROUP BY customer_id;
登录后复制
更快,因为它只需要去除重复的行,而不需要进行分组和聚合。

总而言之,

DISTINCT
登录后复制
用于简单地去除重复行,而
GROUP BY
登录后复制
用于更复杂的分组和聚合操作。 选择哪个取决于你的具体需求。

DISTINCT
登录后复制
GROUP BY
登录后复制

以上就是sql如何使用group by进行数据分组统计 sqlgroup by分组统计的操作教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号