作者:IvanCodes
日期:2025年6月6日
核心目标: 学习如何使用 select 语句从数据库表中高效、准确地检索(查询)所需数据。
基本语法结构(逻辑顺序概览):
select [distinct] column_list_or_expressions -- 5. 选择并处理列
from table_name -- 1. 确定数据源表
[where conditions] -- 2. 过滤行
[group by column_list] -- 3. 分组行
[having conditions_on_groups] -- 4. 过滤分组
[order by column_list [asc | desc]] -- 6. 排序结果
[limit [offset,] row_count]; -- 7. 限制输出行数
(注意:以上数字表示逻辑执行顺序,并非书写顺序)
前提: 操作前需使用 use database_name; 选择目标数据库。以下示例假设已选定数据库,并使用 students 和 products 表。
1. 数据源
指定要从哪个(或哪些)表中检索数据。
- 语法:
... from table_name [alias] ... - 表别名 (
as或省略as): 为表指定临时名称,提高可读性,尤其在JOIN时。
示例:
-- 使用别名 s
select s.first_name, s.major from students as s;
-- 省略 as
select p.product_name from products p;
2. 行过滤 (where)
根据指定条件筛选出符合要求的行。在分组 (group by) 之前执行。
语法:
... where condition;常用条件运算符/子句 :
| 运算符 / 子句 | 含义 | 示例 (仅示意) |
| :-------------------------- | :------------------------------------ | :----------------------------------- |
|=| 等于 |where major = '物理学'|
|>| 大于 |where price > 100|
|<| 小于 |where gpa < 3.0|
|>=| 大于等于 |where stock_quantity >= 50|
|<=| 小于等于 |where price <= 500|
|!=或<>| 不等于 |where major != '化学'|
|and| 逻辑与 (所有条件需满足) |where major = 'CS' and gpa > 3.5|
|or| 逻辑或 (任一条件满足即可) |where price < 100 or stock = 0|
|not| 逻辑非 (条件不成立) |where not major = '金融学'|
|between value1 and value2| 在 value1 和 value2 之间 (含边界) |where price between 100 and 500|
|in (val1, val2, ...)| 值在列表中 |where major in ('物理', '化学')|
|not in (val1, val2, ...)| 值不在列表中 |where product_id not in (501, 504)|
|like pattern| 模式匹配 (%任意多字符,_单字符) |where name like '张%'|
|is null| 判断值是否为 NULL |where major is null|
|is not null| 判断值是否不为 NULL |where email is not null|where子句独立示例:等于 (
=): 查询专业是 '物理学' 的学生。select * from students where major = '物理学';大于 (
>): 查询价格超过 100 元的产品。select product_name, price from products where price > 100;小于 (
<): 查询 GPA 低于 3.0 的学生。select first_name, last_name, gpa from students where gpa < 3.0;大于等于 (
>=): 查询库存量至少为 50 的产品。select product_name, stock_quantity from products where stock_quantity >= 50;小于等于 (
<=): 查询价格不高于 500 元的产品。select product_name, price from products where price <= 500;不等于 (
!=或<>): 查询专业不是 '化学' 的学生。select * from students where major != '化学'; -- 或者 -- select * from students where major <> '化学';逻辑与 (
and): 查询专业是 '计算机科学' 且 GPA 大于 3.5 的学生。select * from students where major = '计算机科学' and gpa > 3.5;逻辑或 (
or): 查询价格低于 100 元或者库存为 0 的产品。select * from products where price < 100 or stock_quantity = 0;逻辑非 (
not): 查询专业不是 '金融学' 的学生。select * from students where not major = '金融学'; -- 注意:通常 `!=` 或 `<>` 更直观范围 (
between ... and ...): 查询价格在 100 元到 500 元之间的产品(包含边界)。select product_name, price from products where price between 100 and 500;集合 (
in (...)): 查询专业是 '物理学' 或 '化学' 的学生。select * from students where major in ('物理学', '化学');集合否定 (
not in (...)): 查询产品 ID 不是 501 或 504 的产品。select * from products where product_id not in (501, 504);模糊匹配 (
like %): 查询产品名称以 '笔记本' 开头的产品。select * from products where product_name like '笔记本%';模糊匹配 (
like %...%): 查询姓氏中包含 '三' 的学生。select * from students where last_name like '%三%';模糊匹配 (
like _): 查询名字刚好是两个字的学生(假设 first_name 存名字)。select * from students where first_name like '__';空值判断 (
is null): 查询没有填写专业的学生。select * from students where major is null;非空判断 (
is not null): 查询填写了邮箱的学生。select * from students where email is not null;
3. 分组 (group by)
将具有相同值的行合并(分组)到单个汇总行中。通常与聚合函数一起使用。
- 语法:
... group by column1, [column2, ...] ... - 规则:
select列表中未包含在聚合函数中的列,必须 出现在group by子句中。分组在where过滤之后进行。 - 聚合函数 (常用):
count(),sum(),avg(),max(),min()
示例:
-- 统计每个专业的学生人数
select major, count(*) as num_students
from students
where major is not null
group by major;
-- 计算每个专业学生的平均 GPA
select major, avg(gpa) as average_gpa
from students
group by major;
4. 分组过滤 (having)
对 group by 分组后的结果进行条件过滤。where 过滤行,having 过滤分组。 having 中通常包含聚合函数。
- 语法:
... group by ... having condition_on_aggregate_results ...
示例:
-- 找出学生人数超过 1 人的专业
select major, count(*) as student_count
from students
group by major
having count(*) > 1;
-- 显示平均 GPA 大于 3.5 的专业
select major, avg(gpa) as avg_gpa
from students
group by major
having avg(gpa) > 3.5;
5. 列选择与处理 (select)
指定最终查询结果中要包含哪些列或表达式的值。
- 语法:
select [distinct] column1, column2, expression as alias, ... - 选项:
distinct: 去除最终结果集中的重复行。- 列别名 (
as或省略as): 为列或表达式结果指定名称。 - 可使用各种函数处理列。
示例:
select student_id as 学号, concat(first_name, ' ', last_name) as `学生全名`, gpa * 10 as scaled_gpa
from students;
6. 结果排序 (order by)
对最终的查询结果集进行排序。
- 语法:
... order by column1 [asc | desc], column2 [asc | desc] ...; - 选项:
asc(升序, 默认),desc(降序)。可按多列、列别名排序。
示例:
select major, avg(gpa) as avg_gpa
from students
group by major
order by avg_gpa desc; -- 按计算出的平均 GPA 降序
7. 限制返回行数 (limit)
限制最终结果集返回的行数。在排序之后执行。
- 语法:
limit row_countlimit offset, row_count(跳过 offset 行)limit row_count offset offset(同上)
示例:
select * from products order by price desc limit 5; -- 最贵的 5 个
select * from students order by gpa desc limit 10 offset 10; -- GPA 排名 11-20
!!! 查询逻辑执行顺序总结 !!!
FROM: 确定源表(及JOIN)。WHERE: 过滤行。GROUP BY: 分组。HAVING: 过滤分组。SELECT: 选择列/表达式,执行函数,应用DISTINCT。ORDER BY: 排序。LIMIT: 限制输出行数。
练习题
假设使用之前的 students 和 products 表数据。
查询
students表中所有 GPA 高于 3.7 的学生的姓名 (first_name,last_name) 和 GPA。
答案:select first_name, last_name, gpa from students where gpa > 3.7;查询
products表中所有产品名称包含 '键盘' 或 '鼠标' 的产品的名称和价格。
答案:select product_name, price from products where product_name like '%键盘%' or product_name like '%鼠标%';查询
students表中所有学生的完整姓名(拼接first_name和last_name并用空格隔开,列别名为full_name)和他们的专业 (major)。
答案:select concat(first_name, ' ', last_name) as full_name, major from students;查询
products表中所有产品的名称和库存量,结果按库存量从高到低排序。
答案:select product_name, stock_quantity from products order by stock_quantity desc;查询
students表中 GPA 排名第 2 和第 3 的学生的学号和 GPA。(提示:使用limit和offset)
答案:select student_id, gpa from students order by gpa desc limit 1, 2; -- 或者 -- select student_id, gpa from students order by gpa desc limit 2 offset 1;查询
students表中有多少个不同的专业?(列别名为distinct_major_count)
答案:select count(distinct major) as distinct_major_count from students where major is not null;查询
products表中每种产品的总价值(价格 库存量),列别名为total_value,并只显示总价值大于 10000 的产品名称和总价值。 答案:*-- 方法一: 在 where 中计算 select product_name, (price * stock_quantity) as total_value from products where (price * stock_quantity) > 10000;查询
students表中每个专业的学生人数,并且只显示学生人数大于等于 2 人的专业。
答案:select major, count(*) as student_count from students where major is not null group by major having count(*) >= 2;查询
products表中价格第二贵的产品信息。(提示:排序后使用limit)
答案:select * from products order by price desc limit 1, 1; -- 或者 -- select * from products order by price desc limit 1 offset 1;查询
students表中姓氏为 '李' (last_name = '李') 或者名字里包含 '三' (first_name like '%三%') 的所有学生信息。
答案:
select * from students where last_name = '李' or first_name like '%三%';
- 对于以下 SQL 查询语句:
select major, avg(gpa) as avg_gpa
from students
where enrollment_year > 2020
group by major
having count(*) >= 2
order by avg_gpa desc
limit 3;
请判断以下哪个操作最先被数据库执行?
A. 计算平均 GPA (avg(gpa))
B. 按 major 分组 (group by major)
C. 过滤入学年份 (where enrollment_year > 2020)
D. 按平均 GPA 排序 (order by avg_gpa desc)
答案: C. 过滤入学年份 (where enrollment_year > 2020)
解释: 根据 SQL 的逻辑执行顺序,WHERE 子句用于过滤原始表的行,是在 GROUP BY、HAVING、SELECT(计算聚合函数)、ORDER BY 和 LIMIT 之前执行的第一步筛选操作(在 FROM 之后)。