news 2026/9/8 6:12:17

SQL GROUP BY 与 HAVING 用法详解:从分组统计到性能优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL GROUP BY 与 HAVING 用法详解:从分组统计到性能优化

SQL 里的 GROUP BY 和 HAVING,是数据库管理系统日常开发与数据分析岗位面试里最高频的两个子句,也是从“会查表”走向“会统计”的分水岭。很多人能背出语法,但一遇到“用 WHERE 还是 HAVING”“为什么 HAVING 不能单独使用”“GROUP BY 之后能不能 SELECT 其他列”这类问题时就卡壳。本文将用一份结构化员工表作为测试数据,从语法、执行顺序、聚合函数配合、性能优化到常见报错排查,完整拆解 GROUP BY 和 HAVING 的用法。

读者看完本文,能够直接在自己的 MySQL、PostgreSQL、SQL Server 或 SQLite 环境中验证所有示例,并能回答绝大多数数据库管理系统相关的 SQL 分组统计面试题。先看核心能力速览,再逐步展开语法细节和实操验证。

1. GROUP BY 与 HAVING 核心能力速览

能力项说明
所属概念SQL 查询语句中的分组子句与分组过滤子句
常用数据库MySQL、PostgreSQL、SQL Server、Oracle、SQLite、DM 等
GROUP BY 作用按一个或多个列对查询结果分组,配合聚合函数做统计
HAVING 作用对 GROUP BY 生成的分组结果进行条件过滤
与 WHERE 区别WHERE 在分组前过滤行,HAVING 在分组后过滤分组
是否必须搭配 GROUP BYHAVING 通常与 GROUP BY 一起使用;单独使用场景较少
典型聚合函数COUNT、SUM、AVG、MAX、MIN、GROUP_CONCAT(方言函数)
执行顺序FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
适用场景分组统计、报表分析、数据清洗、面试笔试、业务看板
常见报错“not functionally dependent on columns in GROUP BY clause”
性能要点分组列建议建立索引;尽量避免对无索引列做大分组统计

从能力速览可以看出,GROUP BY 解决的是“如何分组统计”,HAVING 解决的是“如何过滤统计结果”,两者组合后才构成完整的聚合查询能力。

2. 适用场景与使用边界

2.1 适合什么场景

GROUP BY 和 HAVING 最典型的场景是数据统计。

业务开发中,下面几类需求几乎每天都要写:

  • 统计每个部门的员工人数:按dept_name分组,COUNT(*)统计人数。
  • 统计每个部门的平均薪资:按dept_name分组,AVG(salary)计算平均值。
  • 筛选平均薪资超过阈值的部门:先用GROUP BY dept_name分组,再用HAVING AVG(salary) > 10000过滤。
  • 统计每月入职人数:按DATE_FORMAT(hire_date, '%Y-%m')分组,再COUNT(*)
  • 统计订单表中每个客户的累计消费金额:按customer_id分组,SUM(amount)求总额。
  • 找出重复数据:按业务主键分组,HAVING COUNT(*) > 1定位重复记录。

数据分析师、后端开发、运维人员在写报表 SQL 和接口查询时,都会高频用到这两个子句。

2.2 不建议用在什么场景

GROUP BY 不是万能的。以下场景需要谨慎:

  • 数据量特别大且无分组索引时,GROUP BY 会触发全表扫描和临时表排序,性能可能很差。
  • 业务需要保留分组内明细数据时,GROUP BY只能输出分组列和聚合结果,明细行被折叠;此时更合适的是窗口函数ROW_NUMBER()PARTITION BY或子查询。
  • 需要跨分组计算占比、同比环比时,单独使用 GROUP BY 不够灵活,建议配合窗口函数SUM(...) OVER (PARTITION BY ...)
  • 字符串拼接、按组去重等需求存在数据库方言差异,例如 MySQL 的GROUP_CONCAT、PostgreSQL 的STRING_AGG、SQL Server 的FOR XML PATH,迁移时要注意。

2.3 使用边界与规范提醒

在真实数据库管理系统中操作数据时,有一点必须强调:如果分组统计涉及用户实名信息、手机号、订单金额等敏感数据,测试环境要使用脱敏数据,不能把生产库的原始敏感记录直接导出到个人电脑。SQL 本身是通用技术,但数据访问权限、隐私保护和合规边界需要由执行者自行把控。

3. SQL 执行环境准备

本文示例以 MySQL 语法为主,同时说明 PostgreSQL 和 SQL Server 的差异。读者不需要专门安装完整数据库,也可以使用 SQLite 内存库、在线 SQL 练习平台或本地 Docker 容器验证。

推荐几种准备方式:

# 方式一:Docker 快速启动 MySQL 8 docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:8
# 方式二:Docker 快速启动 PostgreSQL 16 docker run --name pg-test -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d postgres:16

如果本机已经有 MySQL 或 SQL Server 实例,直接使用现有实例即可。创建测试库和测试表:

CREATE DATABASE IF NOT EXISTS sql_demo DEFAULT CHARACTER SET utf8mb4; USE sql_demo; CREATE TABLE employees ( emp_id INT PRIMARY KEY AUTO_INCREMENT, emp_name VARCHAR(50) NOT NULL, dept_name VARCHAR(50) NOT NULL, salary DECIMAL(10, 2) NOT NULL, hire_date DATE NOT NULL );

插入测试数据:

INSERT INTO employees (emp_name, dept_name, salary, hire_date) VALUES ('张三', '技术部', 15000.00, '2021-03-15'), ('李四', '技术部', 18000.00, '2020-07-01'), ('王五', '产品部', 12000.00, '2022-01-10'), ('赵六', '产品部', 11000.00, '2021-11-20'), ('孙七', '产品部', 16000.00, '2019-05-06'), ('周八', '运营部', 9000.00, '2023-02-14'), ('吴九', '运营部', 9500.00, '2022-08-30'), ('郑十', '技术部', 22000.00, '2018-09-12'), ('钱十一', '运营部', 8500.00, '2024-01-05');

后续所有示例都基于这张表。表中包含 4 个部门:技术部 3 人、产品部 3 人、运营部 3 人,薪资覆盖 8500 到 22000。

4. GROUP BY 子句基础用法

4.1 基本语法

GROUP BY 子句用于将查询结果按照一个或多个列进行分组。

SELECT 分组列, 聚合函数(统计列) FROM 表名 WHERE 行级过滤条件 GROUP BY 分组列;

核心逻辑是:数据库先把满足 WHERE 条件的行取出来,然后按照 GROUP BY 指定的列把相同的值归为一组,最后对每组执行聚合函数计算。

4.2 单列分组

统计每个部门的员工人数:

SELECT dept_name, COUNT(*) AS emp_count FROM employees GROUP BY dept_name;

执行结果:

dept_nameemp_count
技术部3
产品部3
运营部3
SELECT dept_name, SUM(salary) AS total_salary, AVG(salary) AS avg_salary, MAX(salary) AS max_salary, MIN(salary) AS min_salary FROM employees GROUP BY dept_name;

执行结果:

dept_nametotal_salaryavg_salarymax_salarymin_salary
技术部55000.0018333.333322000.0015000.00
产品部39000.0013000.000016000.0011000.00
运营部27000.009000.00009500.008500.00

从结果可以看到,GROUP BY 把原始 9 行数据折叠成了 3 个分组,每个分组输出一行统计结果。这就是“分组聚合”的本质。

4.3 多列分组

实际业务经常需要按多个维度分组,例如“按部门和年份统计人数”。

SELECT dept_name, YEAR(hire_date) AS hire_year, COUNT(*) AS emp_count FROM employees GROUP BY dept_name, YEAR(hire_date) ORDER BY dept_name, hire_year;

多列分组的规则是:先按第一列分组,再按第二列分组,只有组合值完全相同的行才归入同一组。这种写法在订单报表、用户分群统计中非常常见。

4.4 GROUP BY 的 SELECT 列限制

这里要重点说明一个坑。在标准 SQL 和 MySQL 8 默认配置下,SELECT 中出现的非聚合列必须出现在 GROUP BY 子句中。

-- 错误示例:emp_name 不在 GROUP BY 中 SELECT dept_name, emp_name, COUNT(*) FROM employees GROUP BY dept_name;

这条语句如果直接执行可能报错,或者在旧 MySQL 版本中会随机返回某个员工的姓名。原因是一个分组里有多个 emp_name,数据库不知道该返回哪一个。

正确做法是只选择分组列和聚合函数:

SELECT dept_name, COUNT(*) FROM employees GROUP BY dept_name;

PostgreSQL 和 SQL Server 在这点上非常严格,只要 SELECT 中出现非分组非聚合列,直接报错。建议所有环境下都遵循“SELECT 的列要么在 GROUP BY 里,要么被聚合函数包裹”的规范。

5. HAVING 子句用法

5.1 HAVING 解决的问题

WHERE 子句无法过滤聚合函数的结果。例如需求是“找出平均薪资超过 10000 的部门”,写成下面这样会报错:

-- 错误示例:WHERE 中不能直接使用聚合函数 SELECT dept_name, AVG(salary) AS avg_salary FROM employees WHERE AVG(salary) > 10000 GROUP BY dept_name;

WHERE 是逐行过滤,过滤发生在分组之前,此时聚合函数还没有计算结果,因此不允许使用AVG(salary)这种聚合条件。正确写法是使用 HAVING:

SELECT dept_name, AVG(salary) AS avg_salary FROM employees GROUP BY dept_name HAVING AVG(salary) > 10000;

执行结果:

dept_nameavg_salary
技术部18333.3333
产品部13000.0000

运营部平均薪资 9000,被过滤掉了。

5.2 HAVING 单独使用

HAVING 不强制要求前面必须有 GROUP BY。在 MySQL 中,可以写:

SELECT COUNT(*) AS total_emp FROM employees HAVING COUNT(*) > 5;

此时整张表被当作一个大分组,COUNT(*) 返回 9,条件成立。但这种写法可读性较差,等价于WHERE COUNT(*) > 5的语义,而标准 SQL 中更推荐使用 WHERE 或子查询。日常开发建议始终让 HAVING 与 GROUP BY 配合出现,语义更清晰。

5.3 HAVING 中可以使用多个聚合条件

HAVING 支持多个条件的组合,也可以使用别名。例如筛选员工数大于 2 人、平均薪资大于 8000 的部门:

SELECT dept_name, COUNT(*) AS emp_count, AVG(salary) AS avg_salary FROM employees GROUP BY dept_name HAVING COUNT(*) > 2 AND AVG(salary) > 8000 ORDER BY avg_salary DESC;

执行结果:

dept_nameemp_countavg_salary
技术部318333.3333
产品部313000.0000
运营部39000.0000

HAVING 中也可以使用 SELECT 中的别名:

SELECT dept_name, AVG(salary) AS avg_salary FROM employees GROUP BY dept_name HAVING avg_salary > 10000;

MySQL 支持在 HAVING 中引用别名,但 PostgreSQL 和 SQL Server 对别名的解析顺序不同,部分场景可能需要重复写聚合表达式。为了可移植性,建议直接写完整聚合表达式。

6. WHERE 与 HAVING 的区别

这部分是面试重点,也是日常开发最容易混淆的地方。

对比维度WHEREHAVING
过滤时机分组之前过滤行分组之后过滤分组
能否使用聚合函数不能可以
是否必须搭配 GROUP BY否,可独立使用通常搭配 GROUP BY
性能影响先缩小数据量,通常更高效分组计算后再过滤,数据量大时开销高
与 SELECT 别名关系通常不能使用 SELECT 别名部分数据库支持
执行顺序先执行后执行

用一个组合查询演示两者同时出现:

需求:统计 2022 年之前入职的员工中,每个部门平均薪资大于 12000 的部门。

SELECT dept_name, AVG(salary) AS avg_salary FROM employees WHERE hire_date < '2022-01-01' GROUP BY dept_name HAVING AVG(salary) > 12000;

先由 WHERE 过滤掉 2022 年之后入职的员工,再由 GROUP BY 分组,最后用 HAVING 筛掉平均薪资不达标的部门。

需要注意,WHERE 和 HAVING 的执行顺序决定了同一个条件写在两个位置效果可能不同。例如“统计部门人数大于 1”的部门,若在 WHERE 中写COUNT(*) > 1会直接报错;若在 WHERE 中写普通行过滤条件,则会先减少参与分组的行数,影响最终分组结果。

所以结论是:行级条件放 WHERE,分组级条件放 HAVING。

7. SQL 子句执行顺序

理解执行顺序是写出正确 SQL 的关键。一个完整查询的标准执行顺序为:

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

逐层拆解:

序号子句作用
1FROM确定数据来源表
2WHERE过滤原始行,剔除不满足条件的记录
3GROUP BY对过滤后的行进行分组
4HAVING过滤分组结果
5SELECT计算选择列、聚合函数、表达式
6ORDER BY对最终结果排序
7LIMIT限制返回行数

这个顺序解释了三个常见问题:

  1. 为什么 WHERE 不能使用聚合函数?因为执行到 WHERE 时还没分组。
  2. 为什么 HAVING 可以使用聚合函数?因为执行到 HAVING 时已经完成分组和聚合计算。
  3. 为什么 ORDER BY 可以使用别名?因为执行到 ORDER BY 时 SELECT 已经计算完成。

在 MySQL 中,GROUP BY 隐式使用顺序排序;如果不需要排序,可以在 GROUP BY 后面加ORDER BY NULL来避免额外排序开销(MySQL 5.7 之前的版本有优化价值,MySQL 8 基本不再需要)。PostgreSQL 不会对 GROUP BY 结果隐式排序,需要排序时显式加 ORDER BY。

8. 高级分组统计场景

8.1 分组后按聚合结果排序

统计每个部门的平均薪资并按平均薪资降序排列:

SELECT dept_name, AVG(salary) AS avg_salary FROM employees GROUP BY dept_name ORDER BY avg_salary DESC;

注意这里 ORDER BY 中使用的是 SELECT 别名avg_salary,在 MySQL 中可以直接使用。如果 ORDER BY 中使用聚合函数,写法为:

ORDER BY AVG(salary) DESC;

8.2 分组后限制返回数量

按部门分组统计总薪资,取薪资最高的两个部门:

SELECT dept_name, SUM(salary) AS total_salary FROM employees GROUP BY dept_name ORDER BY total_salary DESC LIMIT 2;

这条语句在 MySQL、PostgreSQL、SQLite 中都支持。SQL Server 不支持LIMIT,需要改写为SELECT TOP 2 ... ORDER BY total_salary DESC

8.3 分组后查找重复数据

数据清洗场景非常常用。假设员工表里 emp_name 允许重复,要找出重名员工:

SELECT emp_name, COUNT(*) AS cnt FROM employees GROUP BY emp_name HAVING COUNT(*) > 1;

因为当前测试数据没有重名,所以结果为空。如果有一张订单表想找相同订单号重复记录,直接换成GROUP BY order_no HAVING COUNT(*) > 1即可。

8.4 按时间维度分组统计

按月统计入职人数:

SELECT DATE_FORMAT(hire_date, '%Y-%m') AS hire_month, COUNT(*) AS emp_count FROM employees GROUP BY DATE_FORMAT(hire_date, '%Y-%m') ORDER BY hire_month;

PostgreSQL 写法为TO_CHAR(hire_date, 'YYYY-MM'),SQL Server 写法为FORMAT(hire_date, 'yyyy-MM')。时间分组的方言差异在跨数据库迁移时需要单独处理。

8.5 条件聚合

在 GROUP BY 内部用CASE WHEN做条件聚合,可以一次查出多个指标:

SELECT dept_name, COUNT(*) AS total_count, SUM(CASE WHEN salary >= 12000 THEN 1 ELSE 0 END) AS high_salary_count FROM employees GROUP BY dept_name;

执行结果:

dept_nametotal_counthigh_salary_count
技术部33
产品部32
运营部30

这种方式在报表 SQL 中非常实用,一次遍历即可完成多条件统计,效率比多次子查询更高。

8.6 结合窗口函数做组内排名

如果希望在分组统计的同时保留每条记录的组内排名,可以使用窗口函数:

SELECT emp_name, dept_name, salary, ROW_NUMBER() OVER (PARTITION BY dept_name ORDER BY salary DESC) AS rank_in_dept FROM employees;

这里PARTITION BYGROUP BY不同,它不折叠行,而是保持明细数据不变,同时计算组内排名。当 GROUP BY 无法满足“既要明细又要组内统计”的需求时,窗口函数是更好的选择。

9. 性能优化建议

9.1 索引与 GROUP BY

GROUP BY 本质上分两步:先扫描数据,再对分组列排序或使用哈希分组。MySQL 8 使用哈希分组后性能优于早期版本,但如果分组列没有索引,数据量增大后依然可能产生临时文件和磁盘排序。

一个通用的优化原则是:为 GROUP BY 的分组列建立联合索引。

CREATE INDEX idx_emp_dept ON employees(dept_name, hire_date);

如果查询经常按部门和入职时间分组,这个联合索引可以直接覆盖分组列,减少排序开销。如果还要带 WHERE 条件,例如WHERE hire_date >= '2022-01-01' GROUP BY dept_name,索引设计需要遵循最左前缀原则。

9.2 WHERE 前移

先通过 WHERE 缩小参与分组的数据集,再分组,性能最好。例如下面两条语句在数据量大时性能差异明显:

-- 推荐:先过滤再分组 SELECT dept_name, AVG(salary) FROM employees WHERE hire_date >= '2022-01-01' GROUP BY dept_name;
-- 不推荐:分组后再过滤,临时表数据量更大 SELECT dept_name, AVG(salary) FROM employees GROUP BY dept_name HAVING MIN(hire_date) >= '2022-01-01';

二者的语义并不完全等价,但表达了一个核心思路:能用 WHERE 提前过滤的行,不要留到 HAVING 阶段处理。

9.3 避免不必要的分组列

GROUP BY 后面每多一列,分组数可能成倍增加,内存和临时表开销也会增大。写报表 SQL 前先确认是否真的需要多维分组。如果只需要总记录数,直接SELECT COUNT(*) FROM tableGROUP BY分组再数更快。

9.4 使用 EXPLAIN 观察执行计划

MySQL 中使用EXPLAIN查看 GROUP BY 是否触发临时表和文件排序:

EXPLAIN SELECT dept_name, COUNT(*) FROM employees GROUP BY dept_name;

重点观察 Extra 列是否出现Using temporaryUsing filesort。如果出现,说明当前分组列的索引利用不充分,需要考虑调整索引或改写查询。

9.5 分批处理避免大分组

超大表的聚合统计一次性执行容易造成长事务和锁竞争。实际工程中建议按时间范围分批统计,再把结果合并。例如按年循环统计月订单量,然后插入汇总表。这种方式牺牲了实时性,但稳定性更高。

10. 常见问题与排查方法

问题现象可能原因排查方式解决方案
报错“not functionally dependent on columns in GROUP BY clause”SELECT 中包含了非分组列和非聚合列检查 SELECT 列表将非分组列加入 GROUP BY,或包裹在聚合函数中
WHERE 中使用聚合函数报错SQL 语法不允许在 WHERE 中使用聚合函数查看错误语句位置把聚合条件移到 HAVING
HAVING 中使用 SELECT 别名在某些数据库不生效不同数据库对 SELECT 别名解析顺序不同查看数据库版本文档在 HAVING 中写完整聚合表达式
GROUP BY 结果顺序不稳定MySQL 8 不再对 GROUP BY 隐式排序多次执行对比结果显式添加 ORDER BY
分组后想要的明细数据丢失GROUP BY 会折叠行检查业务需求改用窗口函数或子查询
GROUP BY 查询特别慢分组列无索引,或未先 WHERE 过滤执行 EXPLAIN 查看执行计划为分组列建索引,WHERE 条件前置
COUNT(1) 和 COUNT(*) 结果不一致表中存在 NULL 值列对比不同计数列明确统计目标;COUNT(列名) 不包含 NULL 行
使用 GROUP_CONCAT 时字符串过长被截断group_concat_max_len 参数限制查看 MySQL 参数执行 SET SESSION group_concat_max_len = 100000

下面重点拆解两个高频报错。

第一个高频报错是“is not functionally dependent on columns in GROUP BY clause”。这个问题在 MySQL 8、PostgreSQL 和 SQL Server 中都会出现。原因就是 SELECT 列表里出现了既不是分组列、也没有被聚合函数包裹的列。解决方式只有两种:把该列加入 GROUP BY,或者用ANY_VALUE()MAX()MIN()等函数包起来。不过更推荐思考业务是否真的需要取这个列。

第二个高频问题是“WHERE 和 HAVING 用混”。典型表现是过滤聚合结果时习惯性写在 WHERE,然后报语法错误。记住执行顺序即可:WHERE 是先过滤原始行,HAVING 是后过滤分组。如果条件里出现了COUNTSUMAVGMAXMIN,这个条件就只能放 HAVING。

11. 最佳实践

11.1 分组列后置,放 SELECT 最右侧

阅读和调试时,建议先看分组列是什么,再看聚合指标是什么。保持 SELECT 中第一列是分组列,后面依次是聚合列,可读性最好:

SELECT dept_name, COUNT(*) AS emp_count, ROUND(AVG(salary), 2) AS avg_salary FROM employees GROUP BY dept_name;

11.2 注意 NULL 分组

GROUP BY 会把 NULL 值单独作为一组。如果分组列存在 NULL,统计结果中会出现一个NULL分组。需要过滤时可以用HAVING dept_name IS NOT NULL或提前在 WHERE 中过滤。

11.3 聚合结果重命名

聚合函数返回的列名通常很长且不直观。使用别名AS avg_salary可以方便后续排序和程序解析结果集。别名在 ORDER BY 中可以使用,在 HAVING 中建议谨慎使用完整表达式。

11.4 多环境验证

不同数据库管理系统对 GROUP BY 和 HAVING 的语法兼容性有差异。同样的语句在 MySQL 能跑,在 PostgreSQL 或 SQL Server 不一定能跑。团队协作时建议约定统一使用标准 SQL 写法,避免依赖某个数据库的宽松语法。例如不要依赖 MySQL 对非聚合列的宽松处理,尽量做到 SELECT 列全部规范化。

11.5 输出目录与脚本管理

如果经常写分组统计 SQL,建议把常用统计脚本做成数据库视图或存储过程,避免重复粘贴长 SQL。例如可以创建一个部门统计视图:

CREATE VIEW v_dept_stats AS SELECT dept_name, COUNT(*) AS emp_count, AVG(salary) AS avg_salary FROM employees GROUP BY dept_name;

后续查询直接SELECT * FROM v_dept_stats WHERE avg_salary > 10000;,开发效率更高,也便于统一口径。

12. 总结

GROUP BY 和 HAVING 是 SQL 聚合查询的基石。GROUP BY 负责把数据按维度折叠成组,HAVING 负责对分组结果做二次过滤,二者配合聚合函数来完成绝大多数统计需求。理解执行顺序是掌握这两个子句的关键:FROM 先取数,WHERE 先过滤行,GROUP BY 完成分组,HAVING 过滤分组,最后 SELECT 输出结果。写 SQL 时记住一个原则:行级条件放 WHERE,分组条件放 HAVING,SELECT 中要么是分组列要么是聚合列,就不会再出现语法混淆。

建议读者把本文的表结构和 12 条示例 SQL 全部在自己的数据库管理系统中跑一遍,重点关注三点:单列分组与多列分组的区别、WHERE 与 HAVING 的执行顺序差异、以及 GROUP BY 对 SELECT 列的限制。跑通之后再尝试优化部门统计查询的索引,用 EXPLAIN 观察执行计划变化。本文的示例可以直接作为面试前的 SQL 复习资料,收藏备用即可。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 6:10:06

基于MBLS与Copula的光伏功率时空概率预测及Matlab实现

跑过光伏功率预测项目的人应该都有这种感觉&#xff1a;点预测做得再准&#xff0c;遇到连续阴雨天、突发阵性云层遮挡时&#xff0c;结果照样被打得七零八落。光伏功率的波动性和随机性不是靠堆模型就能彻底压住的&#xff0c;真正在电力调度和现货交易里能派上用场的&#xf…

作者头像 李华
网站建设 2026/9/8 6:09:59

6个前端组件搞定精美表单:搜索框、提交按钮与校验反馈实战

简介&#xff1a;这是面向前端初学者与进阶开发者的6个精美表单提交与搜索框设计资源&#xff0c;核心覆盖文本框、下拉菜单、复选框、单选按钮等常见输入元素&#xff0c;以及提交、清除按钮的样式与交互实现&#xff0c;用于解决表单布局单调、搜索框反馈不足等典型UI痛点。压…

作者头像 李华
网站建设 2026/9/8 6:07:14

手把手教你Linux设备驱动开发:从内核编程到调试实战

“硬核宝典”这个说法&#xff0c;真的不是出版社自卖自夸。拿到样书翻了几天&#xff0c;又对着内核源码验证了几个关键章节之后&#xff0c;我可以负责任地讲&#xff1a;如果你想认真学 Linux 设备驱动开发&#xff0c;这本书值得放在手边随时翻。本文不聊虚的&#xff0c;直…

作者头像 李华
网站建设 2026/9/8 6:06:48

武汉光谷天地火锅新店实测,人均80和120到底差在哪

2026年&#xff0c;越来越多的食客在出发前会提前了解武汉光谷天地火锅的消费构成&#xff0c;以便合理安排预算。武汉光谷天地火锅人均多少&#xff1f;从区域市场实测来看&#xff0c;目前周边火锅品牌的人均消费大致集中在80至150元之间。作为该区域新开门店的代表&#xff…

作者头像 李华
网站建设 2026/9/8 6:05:56

ASP.NET GridView与AJAX实战:从UpdatePanel到jQuery的完整方案

简介&#xff1a;这是一份面向ASP.NET开发者的GridView操作实例&#xff0c;基于ASP.NET 4.0与SQL Server 2008环境构建&#xff0c;重点解决自带GridView在数据增删改操作中页面频繁刷新、交互反馈生硬的问题&#xff0c;适用于后台管理模块、信息发布系统等需要快速搭建表格页…

作者头像 李华
网站建设 2026/9/8 6:03:16

含风电并网和集群电动汽车的微电网调度Matlab实现

先说结论&#xff1a;把风电并网和集群电动汽车需求侧响应放进同一个微电网调度模型里&#xff0c;Matlab代码的复杂度会比你预想的高一个量级&#xff0c;但一旦把这条链路跑通&#xff0c;它对调度成本和风电消纳率的改善是实打实的。我最近在Matlab环境里完整搭建了这个优化…

作者头像 李华