提要:通过本教程,你将学习到如何使用子查询来构造复杂的查询。

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;

高于平均租金的电影

上面的方式不是那么高雅,需要两个步骤。我们需要一种将第一步查询结果传递给第二步查询的方法,这就是子查询。

子查询是指嵌套在另一个查询(SELECTINSERTUPDATEDELETE 等)内部的查询,本节我们聚集 SELECT 里的子查询。

把一个查询,通过小括号(())放在 SELECT 语句的 WHERE 子句的表达式里,就构成了子查询:

SELECT
 film_id,
 title,
 rental_rate
FROM
 film
WHERE
 rental_rate > (
 SELECT
 AVG (rental_rate)
 FROM
 film
 );

小括号里面的查询称为子查询内部查询,包含了子查询的查询被称为外部查询

PostgreSQL 按以下顺序执行包含子查询的查询:

  • 首先,执行子查询
  • 获得子查询的结果,并将结果传给外部查询
  • 最后,执行外部查询

在 IN 里使用子查询

子查询返回零个或多个结果,可以把子查询返回的结果放在 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';

影片归还时间

它返回了包含很多行的记录,我们可以把这些记录放在 IN 里,以便获取到影片的详细信息;

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'
 );

在in使用子查询

PostgreSQL 子查询与 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
 );

结果如下:

在exists使用子查询

上一篇:PostgreSQL的差集
下一篇:PostgreSQL的EXISTS