SELECT 语句用于从一个表或多个表中检索出想要的数据行。它是 SQL 中最常用的语句。本文聚焦 SELECT 基础语法速查(单表投影、去重、排序、分页与执行顺序),多条件过滤见《05-数据过滤》,综合组合实战见《06-综合查询实战》。
SELECT 列名 FROM 表名;使用王者荣耀英雄数据表(共 69 个英雄,23 个属性值):
查询单列:
SELECT name FROM heros;查询多列:
SELECT name, hp_max, mp_max, attack_max, defense_max FROM heros;查询所有列:
SELECT * FROM heros;最佳实践:在生产环境中尽量避免使用
SELECT *,明确指定需要的列可以提高查询效率,减少网络传输。
为列名起别名,使结果更易读:
SELECT name AS n, hp_max AS hm, mp_max AS mm FROM heros;
-- 省略 AS 关键字
SELECT name n, hp_max hm FROM heros;在查询结果中添加固定的常数列:
-- 添加字符串常数
SELECT '王者荣耀' AS platform, name FROM heros;
-- 添加数字常数
SELECT 123 AS platform, name FROM heros;使用场景:
使用 DISTINCT 关键字去除重复值:
-- 查询所有攻击范围类型
SELECT DISTINCT attack_range FROM heros;
-- 结果:近战、远程(只有2条记录)注意事项:
-- 对 attack_range 和 name 的组合去重
SELECT DISTINCT attack_range, name FROM heros;
-- 结果:69条记录(因为每个英雄名称不同)-- 升序排序(默认)
SELECT name, hp_max FROM heros ORDER BY hp_max;
-- 降序排序
SELECT name, hp_max FROM heros ORDER BY hp_max DESC;-- 先按 mp_max 升序,再按 hp_max 降序
SELECT name, hp_max FROM heros ORDER BY mp_max, hp_max DESC;排序规则:
| 要点 | 说明 |
|---|---|
| 排序方向 | ASC 升序(默认),DESC 降序 |
| 排序字段 | 可以使用非选择列进行排序 |
| 位置 | ORDER BY 通常位于 SELECT 语句最后 |
| NULL 值 | 排序时 NULL 值的位置因 DBMS 而异:MySQL 升序(ASC)时 NULL 排最前、降序排最后;PostgreSQL 恰好相反(升序时排最后) |
文本类型的排序规则:
-- 按名称排序
SELECT name FROM heros ORDER BY name;
-- 区分大小写排序(需要设置 BINARY)
SELECT name FROM heros ORDER BY BINARY name;-- 返回前 5 条记录
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5;
-- 跳过前 3 条,返回接下来的 5 条
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5 OFFSET 3;
-- 简写形式
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 3, 5;| 数据库 | 语法 |
|---|---|
| MySQL/PostgreSQL/SQLite | LIMIT n 或 LIMIT n OFFSET m |
| SQL Server/Access | TOP n |
| DB2 | FETCH FIRST n ROWS ONLY |
| Oracle | WHERE ROWNUM <= n |
各数据库示例:
-- MySQL
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5;
-- SQL Server
SELECT TOP 5 name, hp_max FROM heros ORDER BY hp_max DESC;
-- DB2
SELECT name, hp_max FROM heros ORDER BY hp_max DESC FETCH FIRST 5 ROWS ONLY;
-- Oracle
SELECT name, hp_max FROM heros WHERE ROWNUM <= 5 ORDER BY hp_max DESC;注意:Oracle 中 ROWNUM 在 ORDER BY 之前生效,上面的写法是"先取 5 条再排序",并非血量最高的前 5 名;Oracle 12c 起建议使用
FETCH FIRST 5 ROWS ONLY(与 DB2 相同的标准语法)。
-- 第 pageIndex 页,每页 pageSize 条记录(伪代码:MySQL 的 LIMIT/OFFSET 只接受常量或占位符,实际使用时需先计算出具体数值)
SELECT * FROM heros
ORDER BY id
LIMIT pageSize OFFSET (pageIndex - 1) * pageSize;
-- 示例:第 2 页,每页 10 条
SELECT * FROM heros
ORDER BY id
LIMIT 10 OFFSET 10;SQL 语句的执行顺序与书写顺序不同:
书写顺序:
SELECT 列名
FROM 表名
WHERE 条件
GROUP BY 分组
HAVING 分组条件
ORDER BY 排序
LIMIT 限制;执行顺序:
1. FROM:确定数据来源
2. WHERE:过滤数据
3. GROUP BY:分组
4. HAVING:过滤分组
5. SELECT:选择列
6. DISTINCT:去重
7. ORDER BY:排序
8. LIMIT:限制结果理解执行顺序的重要性:
-- 错误:WHERE 中使用了 SELECT 别名
SELECT name, score * 2 AS double_score
FROM students
WHERE double_score > 180; -- 错误!
-- 正确:使用原表达式
SELECT name, score * 2 AS double_score
FROM students
WHERE score * 2 > 180;-- 计算字段
SELECT name, hp_max + mp_max AS total FROM heros;
-- 使用函数
SELECT name, UPPER(name) AS upper_name FROM heros;-- CASE WHEN
SELECT
name,
hp_max,
CASE
WHEN hp_max > 7000 THEN '高血量'
WHEN hp_max > 6000 THEN '中血量'
ELSE '低血量'
END AS hp_level
FROM heros;-- UNION:合并并去重
SELECT name FROM heros WHERE role_main = '法师'
UNION
SELECT name FROM heros WHERE role_assist = '法师';
-- UNION ALL:合并不去重
SELECT name FROM heros WHERE role_main = '法师'
UNION ALL
SELECT name FROM heros WHERE role_assist = '法师';-- 不推荐
SELECT * FROM heros;
-- 推荐:只查询需要的列
SELECT name, hp_max, mp_max FROM heros;-- 利用索引排序
SELECT name, hp_max FROM heros ORDER BY id;
-- 避免全表扫描
SELECT name FROM heros WHERE name LIKE '张%'; -- 可以使用索引
SELECT name FROM heros WHERE name LIKE '%张'; -- 无法使用索引-- 总是使用 LIMIT 限制结果数量
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 10;| 操作 | 语法 |
|---|---|
| 查询列 | SELECT 列1, 列2 FROM 表名 |
| 查询所有列 | SELECT * FROM 表名 |
| 起别名 | SELECT 列 AS 别名 FROM 表名 |
| 去重 | SELECT DISTINCT 列 FROM 表名 |
| 排序 | ORDER BY 列 [ASC|DESC] |
| 限制结果 | LIMIT n OFFSET m |
FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMITSELECT *