PostgreSQL 教程: 子查询

九月 3, 2023

摘要:在本教程中,您将学习如何使用 PostgreSQL 子查询来构建复杂的查询。

PostgreSQL 子查询简介

让我们从一个简单的例子开始。

假设我们想找到出租率高于平均出租率的电影。我们可以分两步完成:

  • 使用 SELECT 语句和平均函数 (AVG) 查找平均出租率。
  • 在第二个SELECT语句中使用第一个查询的结果来查找我们想要的电影。

以下查询获取平均出租率:

SELECT
	AVG (rental_rate)
FROM
	film;

SELECT AVG

平均出租率为 2.98。

现在,我们可以获得出租率高于平均出租率的电影:

SELECT
	film_id,
	title,
	rental_rate
FROM
	film
WHERE
	rental_rate > 2.98;

SELECT film whose rental rate is higher than average

代码不太优雅,需要两步。我们想要一种方法将第一个查询的结果传递到一个查询中的第二个查询。解决方案是使用子查询。

子查询是嵌套在另一个查询中的查询,例如SELECT, INSERT, DELETEUPDATE查询语句中。在本教程中,我们仅关注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-292005-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';

SELECT films between

它返回多行,因此我们可以将此查询用作查询语句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'
	);

PostgreSQL Subquery with IN

带有 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
	);

PostgreSQL Subquery with EXISTS

该查询的工作方式类似于customer_id列上的内连接。但是,即使customer表中存在一些对应的行,它也最多为payment表中的每一行返回一行。

在本教程中,您学习了如何使用 PostgreSQL 子查询来构造复杂查询。