SELECT 查询
SELECT 是 SQL 中最常用、最重要的语句,用于从数据库中检索数据。本章将详细介绍 SELECT 语句的各种用法,让你能够灵活地从数据库中查询所需的数据。
基本语法
SELECT 语句结构
sql
SELECT column1, column2, ...
FROM table_name;查询所有列
使用 * 通配符查询表中的所有列:
sql
SELECT * FROM users;注意:在实际应用中,应该明确指定需要的列,而不是使用 *,以提高性能。
查询指定列
只查询需要的列:
sql
SELECT name, age, city FROM users;查询并排序
sql
SELECT name, age
FROM users
ORDER BY age;查询单个表
准备数据
假设我们有以下 users 表:
| id | name | age | city | |
|---|---|---|---|---|
| 1 | 张三 | 25 | 北京 | zhang@example.com |
| 2 | 李四 | 30 | 上海 | li@example.com |
| 3 | 王五 | 28 | 广州 | wang@example.com |
| 4 | 赵六 | 35 | 北京 | zhao@example.com |
| 5 | 钱七 | 22 | 深圳 | qian@example.com |
查询所有数据
sql
SELECT * FROM users;结果:
| id | name | age | city | |
|---|---|---|---|---|
| 1 | 张三 | 25 | 北京 | zhang@example.com |
| 2 | 李四 | 30 | 上海 | li@example.com |
| 3 | 王五 | 28 | 广州 | wang@example.com |
| 4 | 赵六 | 35 | 北京 | zhao@example.com |
| 5 | 钱七 | 22 | 深圳 | qian@example.com |
查询特定列
sql
SELECT name, age FROM users;结果:
| name | age |
|---|---|
| 张三 | 25 |
| 李四 | 30 |
| 王五 | 28 |
| 赵六 | 35 |
| 钱七 | 22 |
使用别名(AS)
为列指定别名,使结果更易读:
sql
SELECT
name AS 姓名,
age AS 年龄,
city AS 城市
FROM users;结果:
| 姓名 | 年龄 | 城市 |
|---|---|---|
| 张三 | 25 | 北京 |
| 李四 | 30 | 上海 |
| 王五 | 28 | 广州 |
| 赵六 | 35 | 北京 |
| 钱七 | 22 | 深圳 |
注意:AS 关键字是可选的,可以省略:
sql
SELECT name 姓名, age 年龄, city 城市
FROM users;去重查询
DISTINCT 关键字
使用 DISTINCT 消除重复的行:
sql
SELECT DISTINCT city FROM users;结果:
| city |
|---|
| 北京 |
| 上海 |
| 广州 |
| 深圳 |
多列去重
对多列的组合进行去重:
sql
SELECT DISTINCT city, age FROM users;计算列
基本计算
在查询中可以对列进行计算:
sql
SELECT
name,
age,
age * 2 AS 双倍年龄
FROM users;结果:
| name | age | 双倍年龄 |
|---|---|---|
| 张三 | 25 | 50 |
| 李四 | 30 | 60 |
| 王五 | 28 | 56 |
| 赵六 | 35 | 70 |
| 钱七 | 22 | 44 |
字符串拼接
sql
-- MySQL
SELECT
name,
CONCAT(name, ' (', city, ')') AS 用户信息
FROM users;
-- PostgreSQL
SELECT
name,
name || ' (' || city || ')' AS 用户信息
FROM users;条件表达式
使用 CASE WHEN 进行条件判断:
sql
SELECT
name,
age,
CASE
WHEN age < 25 THEN '年轻'
WHEN age < 35 THEN '中年'
ELSE '年长'
END AS 年龄分组
FROM users;结果:
| name | age | 年龄分组 |
|---|---|---|
| 张三 | 25 | 中年 |
| 李四 | 30 | 中年 |
| 王五 | 28 | 中年 |
| 赵六 | 35 | 年长 |
| 钱七 | 22 | 年轻 |
限制结果数量
LIMIT 子句
限制返回的行数:
sql
-- 只返回前 3 条记录
SELECT * FROM users LIMIT 3;结果:
| id | name | age | city | |
|---|---|---|---|---|
| 1 | 张三 | 25 | 北京 | zhang@example.com |
| 2 | 李四 | 30 | 上海 | li@example.com |
| 3 | 王五 | 28 | 广州 | wang@example.com |
LIMIT 和 OFFSET 结合
分页查询:
sql
-- 跳过前 2 条,返回接下来的 3 条
SELECT * FROM users LIMIT 3 OFFSET 2;MySQL 的分页语法
sql
-- 返回第 1 页(每页 2 条)
SELECT * FROM users LIMIT 0, 2;
-- 返回第 2 页(每页 2 条)
SELECT * FROM users LIMIT 2, 2;SQL Server 的分页语法
sql
-- 使用 OFFSET-FETCH
SELECT * FROM users
ORDER BY id
OFFSET 0 ROWS
FETCH NEXT 2 ROWS ONLY;排序结果
ORDER BY 子句
使用 ORDER BY 对结果进行排序:
sql
-- 按年龄升序排序
SELECT name, age FROM users ORDER BY age;结果:
| name | age |
|---|---|
| 钱七 | 22 |
| 张三 | 25 |
| 王五 | 28 |
| 李四 | 30 |
| 赵六 | 35 |
降序排序
使用 DESC 关键字:
sql
-- 按年龄降序排序
SELECT name, age FROM users ORDER BY age DESC;结果:
| name | age |
|---|---|
| 赵六 | 35 |
| 李四 | 30 |
| 王五 | 28 |
| 张三 | 25 |
| 钱七 | 22 |
多列排序
sql
-- 先按城市排序,再按年龄排序
SELECT name, city, age
FROM users
ORDER BY city, age;使用列别名排序
sql
SELECT
name,
age * 2 AS 双倍年龄
FROM users
ORDER BY 双倍年龄 DESC;空值处理
COALESCE 函数
返回第一个非 NULL 的值:
sql
-- 假设 email 列可能有 NULL 值
SELECT
name,
COALESCE(email, '未填写邮箱') AS 邮箱
FROM users;NULLIF 函数
如果两个参数相等,返回 NULL:
sql
SELECT
name,
age,
NULLIF(age, 0) AS 检查年龄
FROM users;字符串函数
CONCAT 函数
sql
-- MySQL
SELECT CONCAT(name, ' - ', city) FROM users;UPPER 和 LOWER
sql
SELECT UPPER(name) FROM users; -- 转大写
SELECT LOWER(name) FROM users; -- 转小写SUBSTRING
sql
-- 截取字符串
SELECT SUBSTRING(name, 1, 2) FROM users; -- 取前2个字符LENGTH
sql
-- 获取字符串长度
SELECT LENGTH(name) FROM users;日期函数
CURRENT_DATE / CURRENT_TIME
sql
SELECT CURRENT_DATE; -- 当前日期
SELECT CURRENT_TIME; -- 当前时间DATE_FORMAT(MySQL)
sql
SELECT
name,
DATE_FORMAT(created_at, '%Y-%m-%d') AS 注册日期
FROM users;DATE_PART(PostgreSQL)
sql
SELECT
name,
DATE_PART('year', created_at) AS 年份
FROM users;实战示例
示例 1:查询活跃用户
sql
SELECT
username,
email,
last_login
FROM users
WHERE last_login >= DATE_SUB(NOW(), INTERVAL 30 DAY)
ORDER BY last_login DESC;示例 2:统计各城市用户数
sql
SELECT
city AS 城市,
COUNT(*) AS 用户数
FROM users
GROUP BY city
ORDER BY 用户数 DESC;示例 3:查询高价值客户
sql
SELECT
u.username,
u.email,
SUM(o.total_amount) AS 总消费,
COUNT(o.id) AS 订单数
FROM users u
JOIN orders o ON u.id = o.user_id
GROUP BY u.id
HAVING 总消费 > 1000
ORDER BY 总消费 DESC;性能优化建议
1. 避免使用 SELECT *
sql
-- 不推荐:查询所有列
SELECT * FROM users;
-- 推荐:只查询需要的列
SELECT id, name, email FROM users;2. 使用 WHERE 而不是 HAVING
sql
-- 不推荐:在 HAVING 中过滤
SELECT city, COUNT(*)
FROM users
GROUP BY city
HAVING city = '北京';
-- 推荐:在 WHERE 中过滤
SELECT city, COUNT(*)
FROM users
WHERE city = '北京'
GROUP BY city;3. 合理使用 LIMIT
sql
-- 分页查询
SELECT * FROM users
ORDER BY id
LIMIT 10 OFFSET 20;4. 为常用查询创建索引
sql
-- 为经常查询的列创建索引
CREATE INDEX idx_user_name ON users(name);常见错误
错误 1:列名拼写错误
sql
-- 错误:列名不存在
SELECT nam FROM users;
-- 正确
SELECT name FROM users;错误 2:忘记 FROM 子句
sql
-- 错误:缺少 FROM
SELECT name, age;
-- 正确
SELECT name, age FROM users;错误 3:列别名使用不当
sql
-- 错误:在某些数据库中,别名不能在 WHERE 中使用
SELECT name, age * 2 AS 双倍年龄
FROM users
WHERE 双倍年龄 > 50;
-- 正确:在 WHERE 中使用原始表达式
SELECT name, age * 2 AS 双倍年龄
FROM users
WHERE age * 2 > 50;小结
本章介绍了 SELECT 查询的基本用法:
- 基本语法:SELECT column FROM table
- 查询所有列:使用
*通配符 - 查询指定列:明确列出需要的列
- 列别名:使用 AS 为列指定别名
- 去重查询:使用 DISTINCT
- 计算列:在查询中进行计算
- 限制结果:使用 LIMIT 和 OFFSET
- 排序结果:使用 ORDER BY
- 字符串函数:CONCAT、UPPER、LOWER 等
- 日期函数:CURRENT_DATE、DATE_FORMAT 等
SELECT 是 SQL 中最重要的语句,掌握它的各种用法是学习 SQL 的基础。在下一章中,我们将学习如何使用 WHERE 子句来过滤数据。
下一步: 学习 WHERE 条件,学习如何过滤查询结果。