Skip to content

数据查询

在本章中,我们将学习如何使用 SQL 查询语句从 PostgreSQL 数据库中检索数据。作为数据库最基础也是最常用的操作,掌握查询技巧对于任何数据库应用至关重要。

查询表基础

SELECT 语句概述

要从表中检索数据,我们需要使用 SQL 的SELECT语句。这是数据库操作中最常用的命令之一。一个完整的 SELECT 语句通常包含以下几个部分:

  • 选择列表:指定要返回哪些列
  • 表列表:指定要从哪些表中检索数据
  • 条件限定:(可选)指定哪些行需要被检索

SELECT 语句是 SQL 中最复杂的语句之一,掌握它的基本用法是数据库学习的基础。随着经验的积累,你将能够构建更复杂的查询。

基本查询语法

sql
SELECT 列1, 列2, ... FROM 表名;

语法解释

  • SELECT:关键字,表明这是一个查询操作
  • 列1, 列2, ...:想要获取的列名称
  • FROM:关键字,指定数据来源
  • 表名:要查询的表

查询所有列

假设我们有一个存储天气信息的表weather,如果想检索表中的所有行和所有列,可以使用星号*

sql
SELECT * FROM weather;

运行上述查询,我们将获得如下结果:

     city      | temp_lo | temp_hi | prcp |    date
---------------+---------+---------+------+------------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27
 San Francisco |      43 |      57 |    0 | 1994-11-29
 Hayward       |      37 |      54 |      | 1994-11-29
(3 rows)

这与下面这条明确列出所有列名的查询效果相同:

sql
SELECT city, temp_lo, temp_hi, prcp, date FROM weather;

虽然`SELECT *`在临时查询或探索数据时很方便,但在生产环境的代码中被认为是不好的编程风格。这是因为当表结构变化(如添加新列)时,查询结果也会随之变化,可能导致应用程序错误。

使用表达式和列别名

SELECT 语句不仅可以检索表中的原始列,还可以在查询中使用表达式计算新值:

sql
SELECT city,
       (temp_hi + temp_lo)/2 AS temp_avg,
       date
FROM weather;

上述查询使用了算术表达式(temp_hi + temp_lo)/2计算平均温度,并使用AS子句将结果列重命名为temp_avg

     city      | temp_avg |    date
---------------+----------+------------
 San Francisco |       48 | 1994-11-27
 San Francisco |       50 | 1994-11-29
 Hayward       |       45 | 1994-11-29
(3 rows)

TIP

AS关键字是可选的,但使用它可以让查询更清晰易读。列别名可以让输出结果更有意义,也便于后续处理。

使用 WHERE 子句过滤数据

在实际应用中,我们通常只需要特定条件的数据,而不是表中的所有记录。WHERE子句可以帮助我们筛选出符合特定条件的行:

sql
SELECT * FROM weather
WHERE city = 'San Francisco' AND prcp > 0.0;

这个查询只会返回旧金山下雨天(降水量大于 0)的天气记录:

     city      | temp_lo | temp_hi | prcp |    date
---------------+---------+---------+------+------------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27
(1 row)

WHERE 子句支持多种布尔运算符:

  • AND:两个条件都必须为真
  • OR:至少一个条件为真
  • NOT:条件的否定
业务场景示例

假设你是一家连锁服装店的数据分析师,需要找出所有在寒冷天气(温度低于 40 度)且有降水的日子,以分析特殊天气对销售的影响:

sql
SELECT date, city, temp_lo, prcp
FROM weather
WHERE temp_lo < 40 AND prcp > 0;

对查询结果排序

为了让查询结果更有条理,我们可以使用ORDER BY子句按照指定的列进行排序:

sql
SELECT * FROM weather
ORDER BY city;

结果将按城市名称的字母顺序排列:

     city      | temp_lo | temp_hi | prcp |    date
---------------+---------+---------+------+------------
 Hayward       |      37 |      54 |      | 1994-11-29
 San Francisco |      43 |      57 |    0 | 1994-11-29
 San Francisco |      46 |      50 | 0.25 | 1994-11-27

如果需要更精确的排序,可以指定多个排序列:

sql
SELECT * FROM weather
ORDER BY city, temp_lo;

这会先按城市名排序,对于相同城市的记录再按最低温度排序。

去除重复行

如果我们只关心不同的值而不需要重复项,可以使用DISTINCT关键字:

sql
SELECT DISTINCT city FROM weather;

这将返回表中出现的不同城市名称,而不会重复:

     city
---------------
 Hayward
 San Francisco
(2 rows)

为了确保结果的一致性,我们可以同时使用DISTINCTORDER BY

sql
SELECT DISTINCT city
FROM weather
ORDER BY city;

在某些早期版本的 PostgreSQL 及其他数据库系统中,`DISTINCT`的实现会自动对行进行排序,但现代 PostgreSQL 不保证这一行为。如果排序很重要,请始终明确使用`ORDER BY`。

实际应用示例

sql
-- 查询所有城市的天气记录
SELECT * FROM weather;
sql
-- 查询特定城市的天气
SELECT * FROM weather
WHERE city = 'San Francisco';
sql
-- 计算华氏温度并重命名列
SELECT city,
       date,
       temp_lo AS celsius_low,
       temp_hi AS celsius_high,
       temp_lo * 9/5 + 32 AS fahrenheit_low,
       temp_hi * 9/5 + 32 AS fahrenheit_high
FROM weather;
sql
-- 按日期降序排列,显示最新的天气记录
SELECT * FROM weather
ORDER BY date DESC;

查询最佳实践

实践说明示例
避免使用SELECT *在生产代码中明确指定需要的列SELECT city, date, temp_hi FROM weather
使用有意义的列别名使结果更易理解SELECT temp_hi AS high_temperature
限制返回的行数对于大表查询时提高性能SELECT * FROM weather LIMIT 100
使用索引列作为过滤条件提高查询性能WHERE date BETWEEN '1994-11-01' AND '1994-11-30'
编写可读性强的查询合理缩进和使用注释参考本文中的 SQL 示例

虽然 PostgreSQL 支持复杂的 SQL 查询,但从掌握这些基础操作开始,将帮助你建立坚实的数据库技能基础。

总结

在本章中,我们学习了:

  1. 使用SELECT语句从表中检索数据
  2. 如何选择特定列或所有列
  3. 在查询中使用表达式和列别名
  4. 使用WHERE子句过滤数据
  5. 使用ORDER BY对结果排序
  6. 使用DISTINCT去除重复行