4 minutes
查询与过滤
SELECT 基础
创建练习表并插入数据
-- 创建练习数据库
CREATE DATABASE practice;
\c practice
-- 创建员工表
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
department VARCHAR(30),
salary NUMERIC(10,2),
hire_date DATE,
is_active BOOLEAN DEFAULT true
);
-- 插入测试数据
INSERT INTO employees (name, department, salary, hire_date, is_active) VALUES
('张三', '技术部', 15000, '2023-01-15', true),
('李四', '技术部', 18000, '2022-06-01', true),
('王五', '市场部', 12000, '2023-03-10', true),
('赵六', '市场部', 11000, '2024-01-20', true),
('钱七', '技术部', 22000, '2021-09-01', true),
('孙八', '人事部', 9000, '2024-07-15', true),
('周九', '人事部', 9500, '2023-11-01', true),
('吴十', '技术部', 16000, '2023-06-20', false),
('郑一', '市场部', 10000, '2024-09-01', true),
('陈二', '财务部', 13000, '2022-12-01', true);
基本 SELECT
-- 查询所有列
SELECT * FROM employees;
-- 查询指定列
SELECT name, salary FROM employees;
-- 列别名
SELECT name AS 姓名, salary AS 工资 FROM employees;
-- 列计算
SELECT name, salary, salary * 1.1 AS 涨薪10后 FROM employees;
DISTINCT
-- 查询有哪些部门(去重)
SELECT DISTINCT department FROM employees;
-- 多列去重
SELECT DISTINCT department, is_active FROM employees;
WHERE 条件过滤
比较运算符
-- 精确匹配
SELECT * FROM employees WHERE department = '技术部';
-- 范围比较
SELECT * FROM employees WHERE salary > 15000;
SELECT * FROM employees WHERE salary >= 15000 AND salary <= 20000;
SELECT * FROM employees WHERE salary BETWEEN 10000 AND 15000; -- 包含边界
多条件组合
-- AND:所有条件都满足
SELECT * FROM employees
WHERE department = '技术部' AND salary > 15000;
-- OR:任一条件满足
SELECT * FROM employees
WHERE department = '技术部' OR department = '市场部';
-- NOT:取反
SELECT * FROM employees
WHERE NOT department = '财务部';
-- 组合括号
SELECT * FROM employees
WHERE (department = '技术部' OR department = '市场部')
AND salary > 12000;
IN 列表匹配
-- 等价于多个 OR
SELECT * FROM employees
WHERE department IN ('技术部', '市场部', '财务部');
-- 也可以 NOT IN
SELECT * FROM employees
WHERE department NOT IN ('技术部', '市场部');
⚠️ IN 的坑:WHERE salary IN (子查询) 时,如果子查询返回 NULL,整条 IN 会返回空结果!用 EXISTS 替代。
LIKE 模糊匹配
-- % 匹配任意字符
SELECT * FROM employees WHERE name LIKE '张%'; -- 以"张"开头
SELECT * FROM employees WHERE name LIKE '%部'; -- 以"部"结尾
SELECT * FROM employees WHERE name LIKE '%五%'; -- 包含"五"
-- _ 匹配单个字符
SELECT * FROM employees WHERE name LIKE '张_'; -- "张"加一个字符
PostgreSQL 额外支持:
-- ILIKE 忽略大小写
SELECT * FROM employees WHERE name ILIKE 'zhang%';
NULL 处理
-- IS NULL / IS NOT NULL
SELECT * FROM employees WHERE salary IS NULL;
SELECT * FROM employees WHERE salary IS NOT NULL;
-- 注意:NULL = 0 或 NULL = '' 都不对
-- NULL 和任何值比较都返回 FALSE(包括 NULL = NULL)
常用函数过滤
-- COALESCE:NULL 替换为默认值
SELECT name, COALESCE(salary, 0) AS 工资 FROM employees;
-- NULLIF:如果两个值相等则返回 NULL
SELECT NULLIF(salary, 0) FROM employees;
-- WHERE 中使用函数结果
SELECT * FROM employees
WHERE EXTRACT(YEAR FROM hire_date) = 2023;
SELECT * FROM employees
WHERE hire_date >= '2023-01-01' AND hire_date < '2024-01-01';
ORDER BY 排序
-- 升序(默认)
SELECT * FROM employees ORDER BY salary;
-- 降序
SELECT * FROM employees ORDER BY salary DESC;
-- 多列排序:先按部门升序,同部门按工资降序
SELECT * FROM employees
ORDER BY department ASC, salary DESC;
-- 按别名排序
SELECT name, salary * 12 AS 年收入
FROM employees
ORDER BY 年收入 DESC;
-- NULL 排序控制
SELECT * FROM employees
ORDER BY salary NULLS LAST; -- NULL 排最后(默认)
LIMIT 与 OFFSET 分页
-- 取前 3 条
SELECT * FROM employees ORDER BY salary DESC LIMIT 3;
-- 跳过前 3 条,取 3 条(第 4-6 条)
SELECT * FROM employees ORDER BY salary DESC LIMIT 3 OFFSET 3;
-- 简洁写法(MySQL/PostgreSQL 兼容语法糖)
SELECT * FROM employees ORDER BY salary DESC LIMIT 3 OFFSET 3;
⚠️ LIMIT/OFFSET 的大表性能问题:OFFSET 越大越慢,因为数据库还是要扫描所有之前的数据。大数据量分页建议用"键集分页"(keyset pagination):
-- 键集分页(高效,适合大表)
SELECT * FROM employees
ORDER BY salary DESC, id
WHERE (salary, id) < (上一个salary, 上一个id)
ORDER BY salary DESC, id
LIMIT 3;
实战:综合查询练习
-- 1. 技术部工资 > 15000 的活跃员工
SELECT name, salary, hire_date
FROM employees
WHERE department = '技术部'
AND salary > 15000
AND is_active = true
ORDER BY salary DESC;
-- 2. 2023 年入职的员工
SELECT name, department, hire_date
FROM employees
WHERE hire_date BETWEEN '2023-01-01' AND '2023-12-31'
ORDER BY hire_date;
-- 3. 除了技术部和市场部的员工
SELECT name, department, salary
FROM employees
WHERE department NOT IN ('技术部', '市场部')
ORDER BY salary DESC;
-- 4. 姓名中含"五"且工资超过 10000
SELECT * FROM employees
WHERE name LIKE '%五%' AND salary > 10000;
-- 5. 各部门工资最高的员工
SELECT DISTINCT ON (department)
department, name, salary
FROM employees
ORDER BY department, salary DESC;
小结
本文系统介绍了 SELECT 查询的核心技能:列选择、条件过滤、排序和分页。WHERE 子句是 SQL 中使用频率最高的部分,熟练掌握各种条件组合是高效查询的基础。
下一篇文章将学习如何用聚合函数和 GROUP BY 对数据进行汇总分析。
Summary: SELECT、WHERE 过滤、ORDER BY 排序与 LIMIT 分页。