首页/数据/SQL 速查/SELECT 基础查询

SELECT 基础查询

从表里取数据的基本写法:选择列、指定来源表,再叠加 WHERE / ORDER BY / LIMIT;显式列清单比 SELECT * 更利于稳定输出与减少无关列读取。

SQL 速查数据更新于 2026-10-13

SELECT 是什么

SELECT 是 SQL 中唯一的读取语句,负责从表里取出行与列,本身不修改任何数据。书写顺序是 SELECT 列清单 FROM 表 WHERE 条件 GROUP BY 分组 HAVING 过滤 ORDER BY 排序 LIMIT 条数,但数据库实际按另一套逻辑顺序求值:先从 FROM 确定数据源,再过滤、分组、聚合,最后才计算 SELECT 表达式并排序截断。这条顺序解释了为什么 WHERE 里不能用 SELECT 定义的别名,而 ORDER BY 里可以。语法在 MySQL 8.0、PostgreSQL、SQL Server、Oracle 上基本一致,差异集中在函数名、分页写法与标识符引号规则。

基本信息

适用平台MySQL 8.0 / PostgreSQL 12+ / SQL Server / Oracle 等关系型数据库
语句类型DQL 数据查询,不改变数据,可用只读账号执行
语法骨架SELECT 列清单 FROM 表 [WHERE …] [GROUP BY …] [HAVING …] [ORDER BY …] [LIMIT n]
FROM 可否省略可以,无表查询写作 SELECT 1 + 1,常用于探活与常量计算
权限要求对相关表有 SELECT 权限;跨库跨 schema 查询需额外授权

典型使用场景

  • 按主键或业务键取少量行:接口详情页、后台编辑回显
  • 按条件筛选列表:管理后台的搜索、筛选、分页
  • 统计聚合结果:报表里的计数、求和、分组汇总
  • 给写入做预检:先 SELECT 确认影响范围,再执行 UPDATE 或 DELETE
  • 导出与对账:与数据仓库或下游系统的结果集比对
  • 线上排障:临时确认某条数据是否已按预期落库

基本示例

基本示例
SELECT id, name, city            # 显式列出需要的列,不要依赖 SELECT *
FROM users                       # 数据来源表
WHERE status = 1                 # 只保留有效用户
  AND city IN ('Beijing','Shanghai')   # 多值条件写成 IN 更简洁
ORDER BY created_at DESC         # 按注册时间倒序
LIMIT 20;                        # 只看最近 20 条

SELECT COUNT(*) FROM users;      # 只取一行统计值
SELECT 1 + 1;                    # 无 FROM 的常量查询,用于连接探活

核心子句作用

子句作用求值时机
FROM / JOIN确定数据来源与连接方式最先,决定后续处理的输入行集
WHERE过滤行,条件为 UNKNOWN 的行被丢弃分组之前,不能引用聚合与列别名
GROUP BY把行按列值合并成组WHERE 之后,之后只能引用分组列与聚合函数
HAVING过滤分组后的结果分组之后,条件里可以写聚合函数
SELECT计算输出列,此刻才产生列别名分组之后、排序之前
ORDER BY对最终结果排序SELECT 之后,可用别名与列序号
LIMIT / OFFSET截断返回行数与跳过偏移最后一步执行

逻辑执行顺序

逻辑执行顺序
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY -> LIMIT
# 记忆点:过滤行用 WHERE,过滤组用 HAVING
# 记忆点:别名在 WHERE 不可见,在 ORDER BY 可见

两种分页写法

两种分页写法
-- 传统偏移分页:翻到后面越翻越慢
SELECT id FROM orders ORDER BY id LIMIT 20 OFFSET 4000;

-- 键集分页:用上次最后一条的 id 作起点,深度翻页代价稳定
SELECT id FROM orders WHERE id > 1000 ORDER BY id LIMIT 20;
只写 SELECT 不写 ORDER BY 时,返回顺序由执行计划决定,同一语句两次执行顺序可能不同;分页、Top N、对账导出必须显式排序。
SELECT * 在开发期方便,但接口与导出建议显式列清单:加列、改列顺序都会影响按位置解析结果的程序。
大表上不加 WHERE 的查询会走全表扫描,在线上主库执行可能拖垮实例;先 EXPLAIN 看访问方式,或加 LIMIT 试跑。
MySQL 的 SELECT … FOR UPDATE / FOR SHARE 属于加锁读,只在显式事务里成对使用才有意义,否则锁在语句结束时立即释放。

常见误用对照

  • 想过滤行却写成 HAVING:绕过了 WHERE 的索引能力,扫描量不变
  • 想限流却指望 LIMIT 影响统计:LIMIT 只截断输出,聚合仍按全量算
  • 把 ORDER BY 当成保证:不加 LIMIT 的排序在大结果集上代价高,且排序键重复时顺序仍不稳定
  • 用 WHERE 过滤右表列却不自知:在外连接里这会退化成内连接
  • 在 SELECT 里做业务计算再交给应用排序:口径分散在多处,后续改口径容易漏改

易错点

  • SELECT * 遇到表结构变更会改变返回列,按位置解析结果的应用容易出错
  • WHERE 里不能引用 SELECT 定义的别名,需要写原表达式或套一层子查询
  • 没有 ORDER BY 的分页结果顺序不稳定,翻页时可能出现重复行或漏行
  • 大表无条件查询容易拖慢线上实例,排障前先看 EXPLAIN 的 type 与 rows 估算
  • 把 LIMIT 当过滤条件:LIMIT 只影响返回行数,不参与 WHERE 语义,统计类需求要改用聚合

数据来源与参考

  • MySQL 8.0 Reference Manual · SELECT Statement
  • PostgreSQL Documentation · SELECT
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌