PostgreSQL SELECT 语句(手把手讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在 PostgreSQL 数据库的世界中,SELECT
语句如同一把万能钥匙,能够打开数据检索的无限可能。无论是编程初学者还是中级开发者,掌握 SELECT
语句的精髓,都是高效操作数据库的基石。本文将通过 循序渐进 的方式,结合 实际案例 和 形象比喻,深入浅出地讲解 PostgreSQL 中 SELECT
语句的核心用法。
一、SELECT 语句的基础语法
1.1 基本结构与功能
SELECT
语句是 SQL(Structured Query Language)中最常用的操作之一,其核心作用是从数据库中 检索数据。它的基本语法如下:
SELECT 列名1, 列名2, ...
FROM 表名;
例如,假设有一个名为 employees
的表,包含 id
, name
, department
, salary
四个字段,执行以下语句:
SELECT name, salary FROM employees;
这条语句会返回所有员工的姓名和薪资信息,类似于从图书馆的书架上 精准抽取指定书籍的标题和作者。
1.2 通配符 *
的使用与注意事项
若希望一次性获取表中所有列的数据,可以使用通配符 *
:
SELECT * FROM employees;
但需注意,频繁使用 SELECT *
可能导致性能问题,尤其是在表包含大量列或数据量较大时。因此,只选择需要的列 是优化查询效率的 关键原则。
1.3 别名与计算列
通过 AS
关键字,可以为列或表设置临时名称(别名),提升可读性:
SELECT name AS 员工姓名, salary * 12 AS 年薪 FROM employees;
此外,SELECT
还支持直接进行数学运算或字符串拼接,例如:
SELECT CONCAT('员工:', name, ', 部门:', department) AS 详细信息 FROM employees;
二、数据过滤:WHERE 子句的精细化筛选
2.1 基础条件筛选
WHERE
子句允许根据特定条件过滤数据。例如,筛选薪资高于 10000 的员工:
SELECT name, salary
FROM employees
WHERE salary > 10000;
这类似于在快递分拣中心,根据包裹重量筛选出需要特殊处理的包裹。
2.2 逻辑运算符与比较运算符
- 逻辑运算符:
AND
,OR
,NOT
可组合多个条件。例如,筛选薪资在 8000 到 12000 之间的员工:SELECT * FROM employees WHERE salary > 8000 AND salary < 12000;
- 比较运算符:除了
>
,<
,=
,还可以使用BETWEEN
(区间判断)或IN
(枚举判断):SELECT * FROM employees WHERE department IN ('技术部', '市场部');
2.3 通配符与模糊查询
使用 LIKE
结合通配符 %
和 _
可进行模糊匹配:
%
表示任意字符序列:WHERE name LIKE '张%'
(查找姓“张”的员工);_
表示单个字符:WHERE name LIKE '__阳'
(查找姓名最后两位是“阳”的员工)。
三、排序与分页:让数据更有序
3.1 ORDER BY 子句的排序规则
通过 ORDER BY
可对查询结果进行排序,默认按升序(ASC
),添加 DESC
表示降序:
SELECT name, salary
FROM employees
ORDER BY salary DESC;
这如同将一叠纸条按薪资从高到低排列,方便快速定位最高薪或最低薪的员工。
3.2 LIMIT 和 OFFSET 实现分页
当数据量较大时,分页功能尤为重要:
SELECT * FROM employees
ORDER BY id
LIMIT 10 OFFSET 20;
此语句表示:从第 21 条记录开始,取 10 条数据。这类似于翻阅书本时,直接跳到某一页并阅读固定数量的内容。
四、聚合函数与 GROUP BY:数据的统计与分组
4.1 聚合函数的典型应用场景
PostgreSQL 提供了多个聚合函数,用于统计数据:
COUNT()
:计算行数;SUM()
:计算数值列的总和;AVG()
:计算平均值;MAX()
/MIN()
:获取最大值或最小值。
例如,统计各部门的平均薪资:
SELECT department, AVG(salary) AS 平均薪资
FROM employees
GROUP BY department;
这里 GROUP BY
将数据按 department
分组,再对每个组应用聚合函数。
4.2 HAVING 子句:分组后的条件过滤
HAVING
与 WHERE
类似,但专门用于过滤分组后的结果。例如,筛选平均薪资超过 15000 的部门:
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 15000;
五、JOIN 操作:多表数据的关联查询
5.1 内联接(INNER JOIN)
当需要从多个表中获取相关数据时,JOIN
是核心工具。例如,employees
表与 departments
表通过 department_id
关联:
SELECT e.name, d.department_name, d.location
FROM employees e
INNER JOIN departments d
ON e.department_id = d.id;
这类似于快递分拣系统中,将包裹信息与收件人地址表关联,生成完整的物流信息。
5.2 外联接(LEFT/RIGHT JOIN)
若希望保留左表或右表的所有记录,即使关联条件不匹配,可用外联接:
SELECT e.name, d.department_name
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.id;
此语句会返回所有员工的信息,即使某些员工的部门信息不存在(此时 department_name
为 NULL
)。
5.3 跨库查询与复杂联接
PostgreSQL 还支持跨数据库的联接,或通过 USING
简化同名字段的联接:
SELECT *
FROM employees e
JOIN salaries s
USING (id); -- 假设两表均有同名的 id 字段
六、子查询与 EXISTS:嵌套查询的威力
6.1 子查询的基本用法
子查询是将一个查询的结果嵌套在另一个查询中。例如,查找薪资高于公司平均薪资的员工:
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
子查询 (SELECT AVG(salary) ...)
的结果会被视为一个标量值,供外层查询使用。
6.2 EXISTS 子句:存在性判断
EXISTS
用于判断子查询是否有返回结果:
SELECT name
FROM employees
WHERE EXISTS (
SELECT 1
FROM projects
WHERE projects.employee_id = employees.id
);
此语句会列出所有参与过项目的员工。
七、性能优化:让 SELECT 语句更高效
7.1 索引的合理使用
为高频查询的字段(如 department_id
, salary
)创建索引,可显著提升查询速度:
CREATE INDEX idx_employee_salary ON employees(salary);
但需注意,索引会占用存储空间,并可能降低写入性能。
7.2 避免 SELECT * 的陷阱
仅选择必要列,减少网络传输和内存消耗:
-- 不推荐
SELECT * FROM employees WHERE department = '技术部';
-- 推荐
SELECT id, name, salary FROM employees WHERE department = '技术部';
7.3 使用 EXPLAIN 分析查询计划
通过 EXPLAIN
可查看 PostgreSQL 如何执行查询:
EXPLAIN ANALYZE SELECT * FROM employees WHERE salary > 10000;
此命令会输出查询的执行步骤、时间及资源消耗,帮助定位性能瓶颈。
八、进阶技巧:窗口函数与通用表表达式
8.1 窗口函数:按组计算而不分组
窗口函数允许在不使用 GROUP BY
的情况下,对数据进行分组计算。例如,为每个员工添加部门平均薪资:
SELECT
name,
salary,
AVG(salary) OVER (PARTITION BY department) AS 部门平均薪资
FROM employees;
此语句会为每一行计算所属部门的平均薪资,无需先分组再连接。
8.2 通用表表达式(CTE)
CTE 通过 WITH
子句创建临时结果集,简化复杂查询:
WITH 高薪员工 AS (
SELECT name, salary
FROM employees
WHERE salary > 20000
)
SELECT * FROM 高薪员工
ORDER BY salary DESC;
这类似于先整理出一个“高薪员工名单”,再基于该名单进行排序。
结论
PostgreSQL 的 SELECT
语句是数据库操作的核心工具,其功能远不止“简单查询”——通过灵活运用条件过滤、联接、聚合、子查询等技术,开发者可以完成从基础检索到复杂分析的多样化任务。无论是初学者通过基础语法入门,还是中级开发者通过窗口函数和性能优化提升技能,掌握 SELECT
语句的精髓,都能显著提升数据处理的效率与代码的优雅性。
实践建议:建议读者在本地 PostgreSQL 环境中创建示例表,逐步执行文中代码,并尝试修改条件或字段,观察结果变化。唯有亲手实践,才能真正理解 SELECT
语句的无限可能。