九月 3, 2023
摘要:在本教程中,您将学习如何使用 PostgreSQL 子查询来构建复杂的查询。
PostgreSQL 子查询简介
让我们从一个简单的例子开始。
假设我们想找到出租率高于平均出租率的电影。我们可以分两步完成:
- 使用 SELECT 语句和平均函数 (
AVG
) 查找平均出租率。 - 在第二个
SELECT
语句中使用第一个查询的结果来查找我们想要的电影。
以下查询获取平均出租率:
SELECT
AVG (rental_rate)
FROM
film;
平均出租率为 2.98。
现在,我们可以获得出租率高于平均出租率的电影:
SELECT
film_id,
title,
rental_rate
FROM
film
WHERE
rental_rate > 2.98;
代码不太优雅,需要两步。我们想要一种方法将第一个查询的结果传递到一个查询中的第二个查询。解决方案是使用子查询。
子查询是嵌套在另一个查询中的查询,例如SELECT, INSERT, DELETE
和UPDATE
查询语句中。在本教程中,我们仅关注SELECT
语句。
为了构造子查询,我们将第二个查询放在括号中,并在 WHERE 子句中将其用作表达式:
SELECT
film_id,
title,
rental_rate
FROM
film
WHERE
rental_rate > (
SELECT
AVG (rental_rate)
FROM
film
);
括号内的查询称为子查询或内部查询。包含子查询的查询称为外部查询。
PostgreSQL 按以下顺序执行包含子查询的查询:
- 首先,执行子查询。
- 其次,获取结果并将其传递给外部查询。
- 第三步,执行外部查询。
带有 IN 运算符的子查询
子查询可以返回零行或更多行。要使用此子查询,请在WHERE
子句中使用 IN 运算符。
例如,要获取返回日期在2005-05-29
和2005-05-30
之间的电影,请使用以下查询:
SELECT
inventory.film_id
FROM
rental
INNER JOIN inventory ON inventory.inventory_id = rental.inventory_id
WHERE
return_date BETWEEN '2005-05-29'
AND '2005-05-30';
它返回多行,因此我们可以将此查询用作查询语句WHERE
子句中的子查询,如下所示:
SELECT
film_id,
title
FROM
film
WHERE
film_id IN (
SELECT
inventory.film_id
FROM
rental
INNER JOIN inventory ON inventory.inventory_id = rental.inventory_id
WHERE
return_date BETWEEN '2005-05-29'
AND '2005-05-30'
);
带有 EXISTS 运算符的子查询
以下表达式说明了如何使用带有EXISTS
运算符的子查询:
EXISTS subquery
子查询可以是EXISTS
运算符的输入。如果子查询返回任何行,则EXISTS
运算符返回 true。如果子查询没有返回行,则EXISTS
运算符的结果为 false。
EXISTS
运算符只关心子查询返回的行数,而不关心行的内容,因此,EXISTS
运算符的常见编码约定如下:
EXISTS (SELECT 1 FROM tbl WHERE condition);
请查看以下查询:
SELECT
first_name,
last_name
FROM
customer
WHERE
EXISTS (
SELECT
1
FROM
payment
WHERE
payment.customer_id = customer.customer_id
);
该查询的工作方式类似于customer_id
列上的内连接。但是,即使customer
表中存在一些对应的行,它也最多为payment
表中的每一行返回一行。
在本教程中,您学习了如何使用 PostgreSQL 子查询来构造复杂查询。