PostgreSQL 教程

SQL DISTINCT 关键字

在 PostgreSQL(以及标准 SQL)中,DISTINCT 关键字是进行数据分析和报表生成的强大工具。它允许你从表的一列或多列组合中识别并仅检索唯一的值(即去重后的数据)。当处理包含大量冗余信息的数据集,且需要清晰了解当前存在哪些不同的类别或条目时,这个功能尤为有用。了解如何有效地使用 DISTINCT 是编写高效、准确的 SQL 查询的关键一步。

1. 了解 DISTINCT 子句

DISTINCT 子句通常与 SELECT 语句结合使用,用于从结果集中消除重复的行。它可以应用于表中的一个或多个列。

基础语法如下:

SELECT DISTINCT column1, column2, ...
FROM table_name;

DISTINCT 应用于多个列时,它仅返回这些列中值的唯一组合。请务必记住,DISTINCTNULL(空值)也视为一种特定的、独立的值。这意味着如果某一列包含多个 NULL 值,DISTINCT 在结果集中只会返回一个 NULL 值。

1.1 单列 DISTINCT

让我们从一个简单的例子开始,假设有一个名为 customers(客户)的表,包含以下数据:

customer_id (客户 ID)name (姓名)city (城市)
1John DoeNew York (纽约)
2Jane SmithLondon (伦敦)
3Peter JonesNew York (纽约)
4Mary BrownParis (巴黎)
5John DoeNew York (纽约)

若要检索不重复的城市列表,你可以使用以下查询:

SELECT DISTINCT city
FROM customers;

此查询将返回:

city (城市)
New York (纽约)
London (伦敦)
Paris (巴黎)

请注意,尽管在原始表中“New York”出现了三次,但在结果集中它只出现了一次。

1.2 多列 DISTINCT

现在,假设我们想要查找“姓名”和“城市”的唯一组合。使用相同的 customers 表,我们可以执行以下查询:

SELECT DISTINCT name, city
FROM customers;

此查询将返回:

name (姓名)city (城市)
John DoeNew York (纽约)
Jane SmithLondon (伦敦)
Peter JonesNew York (纽约)
Mary BrownParis (巴黎)

尽管 "John Doe" 和 "New York" 各自单独出现了多次,但由于我们同时对这两列使用了 DISTINCT,系统会将它们作为一个组合来考虑。结果集中 "John Doe" 和 "New York" 的组合只出现了一次(即使客户 ID 1 和 5 具有完全相同的姓名和城市)。

1.3 DISTINCT 与 NULL 值

考虑下面这个名为 products(产品)的表:

product_id (产品 ID)product_name (产品名称)category (类别)
1Laptop (笔记本电脑)Tech (科技)
2Mouse (鼠标)Tech (科技)
3Keyboard (键盘)Tech (科技)
4Monitor (显示器)NULL
5Speaker (音箱)NULL

如果我们运行以下查询:

SELECT DISTINCT category
FROM products;

结果将是:

category (类别)
Tech (科技)
NULL

如你所见,DISTINCTNULL 视为一个独立且唯一的值。在处理可能包含缺失值(空值)的数据时,了解这一点非常重要。

2. 实际案例与演示

让我们在不同的业务场景中探索更多使用 DISTINCT 的实际案例。假设你正在为一个在线商店管理数据库。

2.1 案例 1:查找唯一的产品类别

你想找出 products 表中所有不重复的产品类别。表结构可能如下所示:

product_idproduct_namecategoryprice
1LaptopElectronics (电子产品)1200
2MouseElectronics (电子产品)25
3KeyboardElectronics (电子产品)75
4T-ShirtApparel (服装)20
5JeansApparel (服装)60
6Coffee MakerHome Goods (家居用品)50
7BlenderHome Goods (家居用品)100
8ToasterHome Goods (家居用品)40
9BookBooks (图书)15
10E-BookBooks (图书)10

要检索唯一的类别,你可以使用以下查询:

SELECT DISTINCT category
FROM products;

这将返回:

category
Electronics (电子产品)
Apparel (服装)
Home Goods (家居用品)
Books (图书)

2.2 案例 2:查找送货城市和州/省的唯一组合

考虑一个名为 orders(订单)的表,结构如下:

order_idcustomer_idshipping_city (送货城市)shipping_state (送货州)order_date
1101New YorkNY2023-01-01
2102Los AngelesCA2023-01-02
3101New YorkNY2023-01-03
4103ChicagoIL2023-01-04
5102Los AngelesCA2023-01-05
6104HoustonTX2023-01-06
7105HoustonTX2023-01-07

要找到送货城市和州的唯一组合,你可以使用以下查询:

SELECT DISTINCT shipping_city, shipping_state
FROM orders;

这将返回:

shipping_cityshipping_state
New YorkNY
Los AngelesCA
ChicagoIL
HoustonTX

2.3 案例 3:处理大小写敏感问题

PostgreSQL 默认是区分大小写的。如果你处理的是英文文本数据,这可能会影响 DISTINCT 查询的结果。例如,考虑以下 colors(颜色)表:

color_idcolor_name
1Red
2red
3Green
4Blue

如果你运行以下查询:

SELECT DISTINCT color_name
FROM colors;

结果将包含大小写不同的重复项:

color_name
Red
red
Green
Blue

要将首字母大写的 "Red" 和全小写的 "red" 视为同一个值,你可以使用 LOWER() 函数在应用 DISTINCT 之前将所有值统一转换为小写:

SELECT DISTINCT LOWER(color_name)
FROM colors;

这将返回彻底去重后的结果:

lower
red
green
blue