语法结构解析
SELECT 列1,列2 FROM 表名 [WHERE 条件] [GROUP BY 列] [HAVING 条件] [ORDER BY 列] [LIMIT 行数];
逐词解析
SELECT:
SQL关键字,表示要执行查询操作
必须作为语句的第一个词出现
列1,列2:
指定要查询的列名列表
可以使用
*表示所有列可以使用表达式、函数和别名
多个列用逗号分隔
FROM:
SQL关键字,表示后面跟随的是数据来源的表
必须出现在SELECT子句之后
表名:
指定要查询的数据来源表
可以是单个表或多个表(使用JOIN连接)
可以使用表别名简化引用
[WHERE 条件]:
可选子句,指定筛选行的条件
条件可以使用比较运算符和逻辑运算符
支持子查询作为条件
[GROUP BY 列]:
可选子句,用于对结果集进行分组
通常与聚合函数一起使用
可以指定一个或多个分组列
[HAVING 条件]:
可选子句,对分组后的结果进行筛选
类似于WHERE,但作用于分组后的数据
可以使用聚合函数作为条件
[ORDER BY 列]:
可选子句,指定结果集的排序方式
可以指定ASC(升序,默认)或DESC(降序)
可以按多个列排序,优先级从左到右
[LIMIT 行数]:
可选子句,限制返回的行数
可以指定偏移量:
LIMIT 偏移量, 行数常用于分页查询
完整示例
-- 基本查询:获取特定员工信息 SELECT employee_id, CONCAT(first_name, ' ', last_name) AS full_name, salary, department_name FROM employees JOIN departments ON employees.department_id = departments.department_id WHERE salary > 5000 AND hire_date > '2020-01-01'; -- 分组统计:按部门统计平均薪资 SELECT department_id, department_name, COUNT(*) AS employee_count, AVG(salary) AS avg_salary, MAX(salary) AS max_salary FROM employees JOIN departments USING (department_id) GROUP BY department_id, department_name HAVING AVG(salary) > 6000 ORDER BY avg_salary DESC LIMIT 5; -- 分页查询:获取第2页的产品数据(每页10条) SELECT product_id, product_name, price, category_name FROM products JOIN categories USING (category_id) ORDER BY product_id LIMIT 10, 10;
输出结果:
基本查询:获取特定员工信息输出结果:
+-------------+------------------+--------+-----------------+ | employee_id | full_name | salary | department_name | +-------------+------------------+--------+-----------------+ | 101 | 张 三 | 8500.00| 研发部 | | 102 | 李 四 | 7500.00| 市场部 | | 103 | 王 五 | 6500.00| 人力资源部 | +-------------+------------------+--------+-----------------+ 3 rows in set (0.05 sec)
分组统计:按部门统计平均薪资输出结果:
+---------------+-----------------+----------------+------------+------------+ | department_id | department_name | employee_count | avg_salary | max_salary | +---------------+-----------------+----------------+------------+------------+ | 1 | 研发部 | 15 | 8500.00 | 12000.00 | | 2 | 财务部 | 8 | 7800.00 | 10000.00 | | 3 | 市场部 | 12 | 7200.00 | 9500.00 | +---------------+-----------------+----------------+------------+------------+ 3 rows in set (0.12 sec)
分页查询:获取第2页的产品数据输出结果:
+------------+----------------------+--------+---------------+ | product_id | product_name | price | category_name | +------------+----------------------+--------+---------------+ | 11 | 无线鼠标 | 99.99 | 电子产品 | | 12 | 机械键盘 | 299.99 | 电子产品 | | 13 | 蓝牙耳机 | 199.99 | 电子产品 | | 14 | 办公椅 | 599.99 | 办公家具 | | 15 | 升降桌 | 899.99 | 办公家具 | | 16 | 显示器 | 1299.99| 电子产品 | | 17 | 笔记本电脑 | 4999.99| 电子产品 | | 18 | 投影仪 | 2999.99| 电子产品 | | 19 | 文件柜 | 399.99| 办公家具 | | 20 | 打印机 | 899.99| 办公设备 | +------------+----------------------+--------+---------------+ 10 rows in set (0.03 sec)
输出结果说明
基本查询:
返回符合条件的员工信息,包含员工ID、全名、薪资和部门名称1
结果以表格形式显示,包含列名和数据行3
底部显示查询到的行数和执行时间1
分组统计:
按部门分组计算员工数量、平均薪资和最高薪资5
使用HAVING子句过滤平均薪资大于6000的部门5
结果按平均薪资降序排列并限制为5条记录3
分页查询:
使用LIMIT 10,10实现分页,跳过前10条记录,获取接下来的10条6
结果按产品ID排序,包含产品ID、名称、价格和分类名称3
底部显示查询到的行数和执行时间
示例解析
基本查询示例解析
SELECT子句:employee_id:员工IDCONCAT(first_name, ' ', last_name) AS full_name:拼接姓名为全名并设置别名salary:薪资department_name:部门名称FROM子句:从employees表查询
使用JOIN连接departments表
WHERE子句:salary > 5000:筛选薪资大于5000的员工hire_date > '2020-01-01':筛选2020年后入职的员工
分组统计示例解析
SELECT子句:包含部门ID和名称
使用COUNT统计员工数
使用AVG计算平均薪资
使用MAX获取最高薪资
GROUP BY子句:按部门ID和名称分组
HAVING子句:筛选平均薪资大于6000的部门
ORDER BY子句:按平均薪资降序排序
LIMIT子句:只返回前5条记录
分页查询示例解析
LIMIT 10, 10:跳过前10条记录(第1页)
返回接下来的10条记录(第2页)
关键注意事项
执行顺序:
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
理解执行顺序有助于编写高效查询
性能优化:
避免使用
SELECT *,只查询需要的列为常用查询条件创建索引
大表查询考虑使用LIMIT分批处理
JOIN操作:
明确指定JOIN条件避免笛卡尔积
了解INNER JOIN、LEFT JOIN等区别
子查询:
可以在SELECT、FROM、WHERE等子句中使用子查询
复杂的子查询可以考虑使用临时表或CTE
NULL值处理:
使用IS NULL/IS NOT NULL判断NULL值
聚合函数通常忽略NULL值
别名使用:
列别名提高可读性
表别名简化复杂查询
UNION操作:
可以合并多个SELECT语句的结果
要求列数和数据类型匹配