PostgreSQL 基础查询 #
SELECT 概述 #
SELECT 语句用于从数据库中查询数据。
text
┌─────────────────────────────────────────────────────────────┐
│ SELECT 语句结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ SELECT [DISTINCT] columns │
│ FROM table_name │
│ [ WHERE conditions ] │
│ [ GROUP BY columns ] │
│ [ HAVING conditions ] │
│ [ ORDER BY columns [ASC|DESC] ] │
│ [ LIMIT count [ OFFSET skip ] ]; │
│ │
│ 执行顺序: │
│ 1. FROM 确定数据源 │
│ 2. WHERE 过滤行 │
│ 3. GROUP BY 分组 │
│ 4. HAVING 过滤分组 │
│ 5. SELECT 选择列 │
│ 6. DISTINCT 去重 │
│ 7. ORDER BY 排序 │
│ 8. LIMIT/OFFSET 分页 │
│ │
└─────────────────────────────────────────────────────────────┘
基本查询 #
查询所有列 #
sql
-- 创建示例表
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
department VARCHAR(50),
salary DECIMAL(10, 2),
hire_date DATE,
is_active BOOLEAN DEFAULT TRUE
);
INSERT INTO employees (name, department, salary, hire_date, is_active) VALUES
('Alice', 'Engineering', 80000.00, '2020-01-15', TRUE),
('Bob', 'Sales', 60000.00, '2021-03-20', TRUE),
('Charlie', 'Engineering', 90000.00, '2019-06-10', TRUE),
('Diana', 'Marketing', 70000.00, '2022-02-28', TRUE),
('Eve', 'Sales', 65000.00, '2021-08-05', FALSE),
('Frank', 'Engineering', 85000.00, '2020-11-01', TRUE);
-- 查询所有列
SELECT * FROM employees;
-- 输出:
-- id | name | department | salary | hire_date | is_active
-- ----+---------+-------------+----------+------------+-----------
-- 1 | Alice | Engineering | 80000.00 | 2020-01-15 | t
-- 2 | Bob | Sales | 60000.00 | 2021-03-20 | t
-- 3 | Charlie | Engineering | 90000.00 | 2019-06-10 | t
-- 4 | Diana | Marketing | 70000.00 | 2022-02-28 | t
-- 5 | Eve | Sales | 65000.00 | 2021-08-05 | f
-- 6 | Frank | Engineering | 85000.00 | 2020-11-01 | t
查询指定列 #
sql
-- 查询指定列
SELECT name, department, salary FROM employees;
-- 使用列别名
SELECT
name AS employee_name,
department AS dept,
salary AS annual_salary
FROM employees;
-- 别名可以省略 AS
SELECT name employee_name, department dept FROM employees;
-- 使用表达式
SELECT
name,
salary,
salary * 1.1 AS salary_with_bonus,
ROUND(salary / 12, 2) AS monthly_salary
FROM employees;
DISTINCT 去重 #
sql
-- 查询不重复的部门
SELECT DISTINCT department FROM employees;
-- 输出:
-- department
-- -------------
-- Engineering
-- Sales
-- Marketing
-- 多列去重
SELECT DISTINCT department, is_active FROM employees;
-- 使用 DISTINCT ON(PostgreSQL 特有)
-- 返回每个部门薪资最高的员工
SELECT DISTINCT ON (department)
department,
name,
salary
FROM employees
ORDER BY department, salary DESC;
-- 输出:
-- department | name | salary
-- -------------+---------+----------
-- Engineering | Charlie | 90000.00
-- Marketing | Diana | 70000.00
-- Sales | Eve | 65000.00
WHERE 条件 #
基本条件 #
sql
-- 等于
SELECT * FROM employees WHERE department = 'Engineering';
-- 不等于
SELECT * FROM employees WHERE department != 'Sales';
SELECT * FROM employees WHERE department <> 'Sales';
-- 大于、小于
SELECT * FROM employees WHERE salary > 70000;
SELECT * FROM employees WHERE salary >= 70000;
SELECT * FROM employees WHERE salary < 80000;
SELECT * FROM employees WHERE salary <= 80000;
逻辑运算符 #
sql
-- AND
SELECT * FROM employees
WHERE department = 'Engineering' AND salary > 80000;
-- OR
SELECT * FROM employees
WHERE department = 'Sales' OR department = 'Marketing';
-- NOT
SELECT * FROM employees WHERE NOT is_active;
-- 组合使用(注意优先级)
SELECT * FROM employees
WHERE department = 'Engineering'
AND (salary > 80000 OR is_active = FALSE);
IN 和 NOT IN #
sql
-- IN
SELECT * FROM employees
WHERE department IN ('Engineering', 'Sales');
-- NOT IN
SELECT * FROM employees
WHERE department NOT IN ('Engineering', 'Sales');
-- 子查询
SELECT * FROM employees
WHERE department IN (
SELECT DISTINCT department
FROM employees
WHERE salary > 75000
);
BETWEEN #
sql
-- 范围查询(包含边界)
SELECT * FROM employees
WHERE salary BETWEEN 60000 AND 80000;
-- 日期范围
SELECT * FROM employees
WHERE hire_date BETWEEN '2020-01-01' AND '2021-12-31';
-- NOT BETWEEN
SELECT * FROM employees
WHERE salary NOT BETWEEN 60000 AND 80000;
LIKE 模式匹配 #
sql
-- % 匹配任意字符
SELECT * FROM employees WHERE name LIKE 'A%'; -- 以 A 开头
SELECT * FROM employees WHERE name LIKE '%e'; -- 以 e 结尾
SELECT * FROM employees WHERE name LIKE '%a%'; -- 包含 a
-- _ 匹配单个字符
SELECT * FROM employees WHERE name LIKE '_ob'; -- 第二个字符是 ob
-- ILIKE 不区分大小写
SELECT * FROM employees WHERE name ILIKE 'alice';
-- NOT LIKE
SELECT * FROM employees WHERE name NOT LIKE 'A%';
-- 使用正则表达式
SELECT * FROM employees WHERE name ~ '^A'; -- 以 A 开头
SELECT * FROM employees WHERE name ~* '^a'; -- 以 a 开头(不区分大小写)
SELECT * FROM employees WHERE name !~ '^A'; -- 不以 A 开头
NULL 处理 #
sql
-- IS NULL
SELECT * FROM employees WHERE department IS NULL;
-- IS NOT NULL
SELECT * FROM employees WHERE department IS NOT NULL;
-- NULL 比较的特殊性
SELECT NULL = NULL; -- 结果是 NULL,不是 TRUE
SELECT NULL IS NULL; -- 结果是 TRUE
-- COALESCE 处理 NULL
SELECT
name,
COALESCE(department, 'Unassigned') AS dept,
salary
FROM employees;
-- NULLIF 返回 NULL 如果相等
SELECT NULLIF(salary, 0); -- 如果 salary 是 0,返回 NULL
ORDER BY 排序 #
基本排序 #
sql
-- 升序(默认)
SELECT * FROM employees ORDER BY salary;
SELECT * FROM employees ORDER BY salary ASC;
-- 降序
SELECT * FROM employees ORDER BY salary DESC;
-- 多列排序
SELECT * FROM employees
ORDER BY department ASC, salary DESC;
-- 使用列位置
SELECT name, salary FROM employees
ORDER BY 2 DESC; -- 按第二列排序
NULL 排序 #
sql
-- NULL 值默认排在最后(升序)或最前(降序)
-- 显式指定 NULL 排序位置
SELECT * FROM employees
ORDER BY salary DESC NULLS FIRST;
SELECT * FROM employees
ORDER BY salary ASC NULLS LAST;
表达式排序 #
sql
-- 按表达式结果排序
SELECT name, salary, salary * 1.1 AS bonus_salary
FROM employees
ORDER BY salary * 1.1 DESC;
-- 使用别名排序
SELECT name, salary * 1.1 AS bonus_salary
FROM employees
ORDER BY bonus_salary DESC;
-- 使用 CASE 排序
SELECT * FROM employees
ORDER BY
CASE department
WHEN 'Engineering' THEN 1
WHEN 'Sales' THEN 2
ELSE 3
END;
LIMIT 和 OFFSET 分页 #
LIMIT 限制行数 #
sql
-- 限制返回行数
SELECT * FROM employees LIMIT 3;
-- 获取前 N 名
SELECT * FROM employees
ORDER BY salary DESC
LIMIT 3;
-- LIMIT 0 返回空结果(用于检查语法)
SELECT * FROM employees LIMIT 0;
OFFSET 跳过行 #
sql
-- 跳过前 2 行
SELECT * FROM employees
ORDER BY id
LIMIT 3 OFFSET 2;
-- 分页查询
-- 第 1 页(每页 10 条)
SELECT * FROM employees
ORDER BY id
LIMIT 10 OFFSET 0;
-- 第 2 页
SELECT * FROM employees
ORDER BY id
LIMIT 10 OFFSET 10;
-- 第 N 页
-- OFFSET = (page - 1) * page_size
SELECT * FROM employees
ORDER BY id
LIMIT 10 OFFSET 20; -- 第 3 页
FETCH FIRST 语法 #
sql
-- SQL 标准语法
SELECT * FROM employees
ORDER BY salary DESC
FETCH FIRST 3 ROWS ONLY;
-- 带 OFFSET
SELECT * FROM employees
ORDER BY id
OFFSET 2 ROWS
FETCH FIRST 3 ROWS ONLY;
聚合函数 #
常用聚合函数 #
sql
-- COUNT 计数
SELECT COUNT(*) FROM employees; -- 总行数
SELECT COUNT(department) FROM employees; -- 非 NULL 行数
SELECT COUNT(DISTINCT department) FROM employees; -- 不重复值数量
-- SUM 求和
SELECT SUM(salary) FROM employees;
-- AVG 平均值
SELECT AVG(salary) FROM employees;
SELECT ROUND(AVG(salary), 2) FROM employees; -- 保留两位小数
-- MAX/MIN 最大/最小值
SELECT MAX(salary), MIN(salary) FROM employees;
-- 组合使用
SELECT
COUNT(*) AS total_count,
COUNT(DISTINCT department) AS dept_count,
SUM(salary) AS total_salary,
ROUND(AVG(salary), 2) AS avg_salary,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary
FROM employees;
GROUP BY 分组 #
sql
-- 按部门分组统计
SELECT
department,
COUNT(*) AS employee_count,
SUM(salary) AS total_salary,
ROUND(AVG(salary), 2) AS avg_salary
FROM employees
GROUP BY department;
-- 输出:
-- department | employee_count | total_salary | avg_salary
-- -------------+----------------+--------------+------------
-- Engineering | 3 | 255000.00 | 85000.00
-- Sales | 2 | 125000.00 | 62500.00
-- Marketing | 1 | 70000.00 | 70000.00
-- 多列分组
SELECT
department,
is_active,
COUNT(*) AS count,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department, is_active
ORDER BY department, is_active;
HAVING 过滤分组 #
sql
-- HAVING 过滤分组结果(WHERE 过滤行)
SELECT
department,
COUNT(*) AS employee_count,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING COUNT(*) > 1;
-- 平均薪资大于 70000 的部门
SELECT
department,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 70000;
-- WHERE 和 HAVING 结合
SELECT
department,
COUNT(*) AS count,
AVG(salary) AS avg_salary
FROM employees
WHERE is_active = TRUE
GROUP BY department
HAVING COUNT(*) > 1
ORDER BY avg_salary DESC;
聚合函数与 NULL #
sql
-- 聚合函数忽略 NULL 值
SELECT
COUNT(*) AS total, -- 所有行
COUNT(department) AS non_null, -- 非 NULL 行
AVG(salary) AS avg -- 忽略 NULL
FROM employees;
-- 使用 COALESCE 处理 NULL
SELECT AVG(COALESCE(salary, 0)) FROM employees;
表达式和函数 #
算术运算 #
sql
SELECT
name,
salary,
salary + 10000 AS salary_plus_bonus,
salary * 1.1 AS salary_with_increase,
salary / 12 AS monthly_salary,
salary % 1000 AS remainder
FROM employees;
字符串函数 #
sql
SELECT
name,
UPPER(name) AS upper_name,
LOWER(name) AS lower_name,
LENGTH(name) AS name_length,
CONCAT(name, ' - ', department) AS full_info,
name || ' (' || department || ')' AS formatted_name,
SUBSTRING(name, 1, 3) AS short_name,
LEFT(name, 3) AS first_three,
RIGHT(name, 3) AS last_three,
REPLACE(name, 'a', 'A') AS replaced_name,
INITCAP(name) AS capitalized
FROM employees;
日期函数 #
sql
SELECT
name,
hire_date,
CURRENT_DATE AS today,
CURRENT_TIMESTAMP AS now,
AGE(hire_date) AS employment_duration,
EXTRACT(YEAR FROM hire_date) AS hire_year,
EXTRACT(MONTH FROM hire_date) AS hire_month,
DATE_TRUNC('year', hire_date) AS year_start,
hire_date + INTERVAL '1 year' AS one_year_later,
hire_date - INTERVAL '1 month' AS one_month_ago
FROM employees;
条件表达式 #
sql
-- CASE WHEN
SELECT
name,
salary,
CASE
WHEN salary >= 80000 THEN 'High'
WHEN salary >= 60000 THEN 'Medium'
ELSE 'Low'
END AS salary_level
FROM employees;
-- CASE 简单形式
SELECT
name,
department,
CASE department
WHEN 'Engineering' THEN 'Tech'
WHEN 'Sales' THEN 'Business'
ELSE 'Other'
END AS dept_type
FROM employees;
-- COALESCE 返回第一个非 NULL 值
SELECT
name,
COALESCE(department, 'Unassigned') AS dept
FROM employees;
-- NULLIF 如果相等返回 NULL
SELECT NULLIF(salary, 0);
学习路径 #
text
基础阶段
├── 数据库操作
├── 表操作
├── 数据插入
├── 数据更新
├── 数据删除
└── 基础查询(本文)
进阶阶段
├── 高级查询
└── 多表查询
下一步 #
掌握了基础查询后,接下来学习 高级查询,了解子查询、CTE 和窗口函数!
最后更新:2026-03-29