MySQL怎么进行单表查询?单表查询的语句

来源:语言推理作者:永濑头衔:网络博主
导读:本期聚焦于永濑创作的《MySQL怎么进行单表查询?单表查询的语句》,敬请观看详情。单表查询是SQL中最基础也最高频的操作,但真正把一条SELECT写清楚,需要理解字段列表、条件过滤、排序分页以及聚合统计之间的配合。本文从SELECT语法结构入手,结合员工表实例,说明SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY、LIMIT等子句在单表场景下的写法和执行顺序,并演示聚合函数、模糊查询、范围过滤和空值判断的常见用法。同时给出避免全表扫描、合理利用索引的优化建议,帮助读者在数据量增大后仍能保持查询效率。内容适合MySQL初学者和需要系统梳理单表查询语法的开发人员。

单表查询的完整语句并不是只有SELECT和FROM。一条典型的单表查询可能包含字段列表、过滤条件、分组字段、聚合筛选、排序规则和返回行数限制。理解这些子句的组合规则以及MySQL实际执行它们的先后顺序,是写出准确高效查询的前提。本文以一张员工表为例,从最基础的查询开始,逐步加入条件、排序、分组和聚合,最终梳理出一条完整SELECT语句的正确书写方式。

MySQL怎么进行单表查询?单表查询的语句

一、单表查询的基础语法与执行顺序

单表查询最常用的形式是从一张表中读取若干列。最基本的语法结构为:SELECT 列名 FROM 表名 WHERE 条件。当需要查询所有列时,可以使用星号通配符,但在实际开发中建议尽量避免使用SELECT *,因为读取不需要的列会增加数据库I/O和网络传输开销,尤其是表结构后续增加大字段时,原本正常的查询可能突然变慢。

为了演示方便,先创建一张员工表,并插入几条测试数据。建表语句如下:

CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    department VARCHAR(50),
    salary DECIMAL(10,2),
    hire_date DATE,
    status TINYINT
);

INSERT INTO employees (name, department, salary, hire_date, status) VALUES
('张伟', '技术部', 12000.00, '2021-05-12', 1),
('李娜', '产品部', 9500.00, '2022-03-08', 1),
('王强', '技术部', 7800.00, '2023-07-21', 1),
('赵敏', '市场部', 6800.00, '2020-11-30', 0),
('刘洋', '技术部', 15000.00, '2019-02-18', 1),
('陈静', '产品部', 8200.00, '2022-09-01', 1);

如果只想查看员工姓名、部门和薪资,可以这样写:

SELECT name, department, salary
FROM employees;

很多人以为MySQL会按照SELECT中字段出现的顺序从表里取数,但实际上一条完整查询的逻辑执行顺序和书写顺序并不一致。MySQL处理查询时,通常先找到数据来源表,再根据WHERE条件过滤行,之后才计算SELECT后面的字段,接下来执行GROUP BY分组和HAVING筛选,最后处理ORDER BY排序和LIMIT限制。也就是说,书写顺序是SELECT - FROM - WHERE - GROUP BY - HAVING - ORDER BY - LIMIT,而执行顺序是FROM - WHERE - GROUP BY - HAVING - SELECT - ORDER BY - LIMIT。这个差异对于理解字段别名、聚合函数的使用位置非常关键。

比如在WHERE子句中不能直接使用SELECT里定义的别名,因为WHERE执行时SELECT还没有发生。以下写法在MySQL中会报错或得不到预期结果:

SELECT name, salary AS sal
FROM employees
WHERE sal > 8000;

正确做法是直接使用原始列名salary,或者把条件中的表达式写完整。只有在ORDER BY中才可以使用SELECT里的别名,因为ORDER BY执行顺序排在SELECT之后。

二、WHERE条件过滤与排序分页

WHERE子句用于从表中选择满足条件的行,是单表查询中最频繁使用的部分。MySQL支持比较运算符、逻辑运算符以及多种条件表达式。比较运算符包括等于、大于、小于、不等于等,逻辑运算符包括ANDORNOT。例如查询技术部中薪资不低于8000且状态为在职的员工:

SELECT name, salary
FROM employees
WHERE department = '技术部'
  AND salary >= 8000
  AND status = 1;

当需要在一个集合中匹配多个值时,使用IN比多个OR条件更清晰。例如同时查询技术部和产品部的员工:

SELECT name, department
FROM employees
WHERE department IN ('技术部', '产品部');

对于连续范围,可以使用BETWEEN关键字。注意BETWEEN包含边界值,等价于大于等于起始值并且小于等于结束值。例如查询入职日期在2021年1月1日到2023年12月31日之间的员工:

SELECT name, hire_date
FROM employees
WHERE hire_date BETWEEN '2021-01-01' AND '2023-12-31';

模糊查询使用LIKE配合百分号和下划线,其中百分号表示任意长度的任意字符,下划线表示单个任意字符。例如查询姓张的员工:

SELECT name
FROM employees
WHERE name LIKE '张%';

如果字段允许NULL值,不能使用等号判断NULL,而要用IS NULL或IS NOT NULL。例如查询部门不为空的员工:

SELECT name, department
FROM employees
WHERE department IS NOT NULL;

排序使用ORDER BY,默认按升序排列,也可以使用ASCDESC指定方向。多列排序时,先按第一列排序,第一列相同再按第二列排序。例如按薪资从高到低排列,薪资相同时按姓名升序排列:

SELECT name, salary
FROM employees
WHERE salary > 5000
ORDER BY salary DESC, name ASC;

限制返回行数使用LIMIT。LIMIT可以接受一个参数表示返回前几行,也可以接受两个参数表示从第几行开始返回几行,偏移量从0开始。例如按薪资降序排列后,跳过前3条再取5条:

SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 3, 5;

LIMIT在分页场景中使用频繁,但当偏移量很大时性能会变差,因为MySQL需要先扫描并丢弃前面大量行。例如LIMIT 100000, 20需要读取100020行,只返回20行。对于大表分页,更推荐使用基于主键或索引的延迟关联、游标分页等方式,避免单纯依赖大偏移量。

三、聚合函数与GROUP BY分组查询

单表查询除了逐行返回数据,还经常需要对整个表或某些分组进行统计。MySQL提供COUNT、SUM、AVG、MAX、MIN等聚合函数。COUNT用于统计行数,SUM计算总和,AVG计算平均值,MAX和MIN分别取最大值和最小值。例如统计员工总人数:

SELECT COUNT(*) AS total
FROM employees;

如果只想知道某个部门有多少人,就需要使用GROUP BY把相同部门的行归为一组,再对每组应用聚合函数。例如按部门统计人数:

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

GROUP BY后面可以跟多个字段,表示按多个维度的组合进行分组。分组后SELECT中出现的非聚合列通常必须出现在GROUP BY中,否则数据库无法确定取哪一行的值。MySQL在非严格模式下可能允许这种写法,但结果具有不确定性,不建议依赖。例如下面的查询虽然可能执行成功,但name列没有出现在GROUP BY中,不同版本或不同SQL模式下结果可能不同:

SELECT department, name, COUNT(*)
FROM employees
GROUP BY department;

正确的方式是让SELECT中的非聚合列和GROUP BY保持一致,或者使用聚合函数包裹需要统计的列。例如按部门统计平均薪资:

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;

如果需要对分组后的结果进一步过滤,不能使用WHERE,而要使用HAVING。WHERE在分组前过滤原始行,HAVING在分组后过滤聚合结果。例如查询平均薪资大于10000的部门:

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

这里WHERE无法完成这个任务,因为WHERE执行时聚合函数还没有计算。如果既需要过滤原始行,又需要过滤分组结果,可以同时使用WHERE和HAVING。例如只统计在职员工,并筛选出人数大于1的部门:

SELECT department, COUNT(*) AS emp_count
FROM employees
WHERE status = 1
GROUP BY department
HAVING COUNT(*) > 1;

聚合查询还可以和排序、限制结合使用。例如找出平均薪资最高的两个部门:

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
ORDER BY avg_salary DESC
LIMIT 2;

四、单表查询的常见问题与优化建议

单表查询看似简单,但随着数据量增长,不合理的写法会带来明显的性能问题。首先是字段列表,尽量只选择需要的列,而不是使用SELECT *。指定列可以让MySQL只读取必要的数据,也能减少网络传输量。如果表中有TEXT、BLOB等大字段,SELECT *还会把这些大字段全部读取出来,对性能影响很大。

其次是条件过滤。尽量让WHERE条件能够利用索引,避免对索引列进行函数运算或隐式类型转换。例如下面的写法无法使用hire_date列上的索引,因为对列使用了YEAR函数:

SELECT name, salary
FROM employees
WHERE YEAR(hire_date) = 2023;

应该改为范围查询,让数据库可以直接利用索引:

SELECT name, salary
FROM employees
WHERE hire_date >= '2023-01-01'
  AND hire_date < '2024-01-01';

同样,模糊查询中如果把百分号放在字符串开头,例如LIKE '%技术%',MySQL将无法使用普通索引,只能进行全表扫描。如果业务确实需要中间匹配,可以考虑使用全文索引或专门的搜索引擎。如果只需要前缀匹配,写成LIKE '技术%'则有条件走索引。

对于深分页问题,可以通过记录上一页最后一条主键值来优化。例如第一页取到了id为10000的记录,下一页可以写成:

SELECT id, name, salary
FROM employees
WHERE id > 10000
ORDER BY id ASC
LIMIT 20;

这种写法利用主键索引直接定位到偏移位置,不会随着页数增加而快速变慢。当然这种方式只适用于按主键或其他可比较字段连续翻页的场景。如果排序字段不唯一,还需要结合多个字段确保分页稳定。

最后,建议在开发过程中使用EXPLAIN查看执行计划。通过观察type、key、rows等字段,可以判断查询是否使用了索引、扫描了多少行、是否存在文件排序或临时表。单表查询调优的核心在于减少扫描行数和避免不必要的排序、回表操作。只要养成先看执行计划再优化的习惯,大部分单表查询性能问题都能在早期被发现和解决。

MySQL单表查询SELECT语句WHERE条件修改时间:2026-08-24 05:53:05

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。