PostgreSQL-03-入门篇-过滤数据

1. WHERE

WHERE 子句概述

SELECT语句返回表中一列或多列的所有行。要选择满足指定条件的行,可以使用WHERE子句。

PostgreSQL 的WHERE子句的语法如下:

SELECT select_list
FROM table_name
WHERE condition
ORDER BY sort_expression

WHERE子句出现在SELECT语句的FROM子句之后。WHERE子句使用condition来过滤从SELECT列表子句返回的行。

condition的计算结果必须为真、假或未知。它可以是布尔表达式或使用ANDOR运算符的布尔表达式的组合。

该查询仅返回满足WHERE子句中condition的行。换句话说,只有导致condition计算结果为 true 的行才会包含在结果集中。

PostgreSQL 计算WHERE子句的时间点,在FROM子句之后,在SELECT列表和ORDER BY子句之前:

在这里插入图片描述

如果在SELECT列表子句中使用列别名,则不能在WHERE子句中使用它们。

除了SELECT语句之外,您还可以使用UPDATEDELETE语句中的WHERE子句来指定要更新或删除的行。

要构成WHERE子句中的条件,请使用比较运算符和逻辑运算符:

运算符描述
=等于
>大于
<小于
>=大等于
<=小等于
<> 或 !=不等于
AND逻辑运算符 AND
OR逻辑运算符 OR
IN如果值与列表中的任何值匹配,则返回 true
BETWEEN如果值介于某个值范围之间,则返回 true
LIKE如果值与模式匹配则返回 true
IS NULL如果值为 NULL,则返回 true
NOT对其他运算符的结果求反
WHERE 子句示例
1) 使用 WHERE 子句和等于运算符 (=) 示例

以下语句使用WHERE子句查找名字为Jamie的客户:

SELECT
last_name,
first_name
FROM
customer
WHERE
first_name = 'Jamie';
2) 使用 WHERE 子句和 AND 运算符示例

以下示例通过使用AND逻辑运算符组合两个布尔表达式,来查找名字为Jamie和姓氏为rice的客户:

SELECT
last_name,
first_name
FROM
customer
WHERE
first_name = 'Jamie' AND
    last_name = 'Rice';
3) 使用 WHERE 子句和 OR 运算符示例

此示例使用OR运算符查找姓氏为Rodriguez或名字为Adam的客户:

SELECT
first_name,
last_name
FROM
customer
WHERE
last_name = 'Rodriguez' OR 
first_name = 'Adam';
4) 使用 WHERE 子句和 IN 运算符示例

如果要将某个字符串与列表中的任何字符串进行匹配,可以使用IN运算符。

例如,以下语句返回名字为Ann,或Anne,或Annie的客户:

SELECT
first_name,
last_name
FROM
customer
WHERE 
first_name IN ('Ann','Anne','Annie');
5) 使用 WHERE 子句和 LIKE 运算符示例

要查找与指定模式匹配的字符串,可以使用LIKE运算符。以下示例返回名字以字符串Ann开头的所有客户:

SELECT
first_name,
last_name
FROM
customer
WHERE 
first_name LIKE 'Ann%'

%称为匹配任何字符串的通配符。模式'Ann%'匹配任何以'Ann'开头的字符串。

6) 将 WHERE 子句与 BETWEEN 运算符一起使用的示例

以下示例使用BETWEEN运算符查找名字以字母A开头且包含 3 到 5 个字符的客户。

如果某个值在某个值范围内,则BETWEEN运算符返回 true。

SELECT
first_name,
LENGTH(first_name) name_length
FROM
customer
WHERE 
first_name LIKE 'A%' AND
LENGTH(first_name) BETWEEN 3 AND 5
ORDER BY
name_length;

在此示例中,我们使用LENGTH()函数获取输入字符串的字符数。

7) 使用带有不等于运算符 (<>) 的 WHERE 子句示例

此示例查找名字以Bra开头且姓氏不是Motley的客户:

SELECT 
first_name, 
last_name
FROM 
customer 
WHERE 
first_name LIKE 'Bra%' AND 
last_name <> 'Motley';

请注意,您可以互换使用!=运算符和<>运算符,因为它们是等效的。

2. LIMIT

PostgreSQL LIMIT 子句简介

PostgreSQL 的 LIMIT 子句是 SELECT 语句的一个可选部分,它可以帮助您限制查询结果中的行数。

语法

LIMIT 子句的基本语法如下:

SELECT select_list 
FROM table_name
ORDER BY sort_expression
LIMIT row_count;

这条语句会返回查询结果中的 row_count 行。如果 row_count 设置为零,查询将返回空集;如果设置为 NULL,查询将返回所有行。

如果您想在返回 row_count 行之前跳过一些行,请在 LIMIT 子句之后放置 OFFSET 子句,如下所示:

SELECT select_list
FROM table_name
LIMIT row_count OFFSET row_to_skip;

这条语句首先跳过 row_to_skip 行,然后返回查询生成的 row_count 行。如果 row_to_skip 为零,则该语句将像没有 OFFSET 子句一样工作。

由于表可能以未指定的顺序存储行,因此当您使用 LIMIT 子句时,应始终使用 ORDER BY 子句来控制行顺序。如果不使用 ORDER BY 子句,则可能会得到具有未指定行顺序的结果集。

PostgreSQL LIMIT 示例
1) 使用 LIMIT 限制返回行数的示例

此示例使用 LIMIT 子句来获取按 film_id 排序的前五部电影:

SELECT
film_id,
title,
release_year
FROM
film
ORDER BY
film_id
LIMIT 5;
2) 使用 LIMIT 和 OFFSET 的示例

要检索按 film_id 排序的从第四部开始的 4 部电影,请同时使用 LIMITOFFSET 子句,如下所示:

SELECT
film_id,
title,
release_year
FROM
film
ORDER BY
film_id
LIMIT 4 OFFSET 3;
3) 使用 LIMIT OFFSET 获取头部/底部 N 行

通常,经常使用 LIMIT 子句从表中选择具有最高或最低值的行。

例如,要获取租赁费用最高的 10 部电影,您可以按租赁费率降序对电影进行排序,并使用 LIMIT 子句获取前 10 部电影。以下查询说明了这个想法:

SELECT
film_id,
title,
rental_rate
FROM
film
ORDER BY
rental_rate DESC
LIMIT 10;

3. FETCH

FETCH 子句简介

为了限制查询返回的行数,您经常使用LIMIT子句。LIMIT子句被许多关系数据库管理系统广泛使用,例如 MySQL、H2 和 HSQLDB。但是,LIMIT子句不是 SQL 标准。

为了符合 SQL 标准,PostgreSQL 支持FETCH子句来检索查询返回的行数。

请注意,FETCH子句是在 SQL:2008 中作为 SQL 标准的一部分引入的。

下面说明了 PostgreSQL 的FETCH子句的语法:

OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ row_count ] { ROW | ROWS } ONLY

在这个语法中:

  • ROWROWS的同义词,FIRSTNEXT的同义词。所以你可以互换使用它们。
  • start是一个整数,必须为零或正数。默认情况下,如果未指定OFFSET子句,则该值为零。如果start大于结果集中的行数,则不返回任何行;
  • row_count是 1 或更大。默认情况下,如果不显式指定row_count,则默认值为 1。

由于表中存储的行顺序是未指定的,因此在使用FETCH子句时应始终带有ORDER BY子句,以使返回的结果集中的行顺序一致。

请注意,在 SQL:2008 标准中,OFFSET子句必须位于FETCH子句之前。但是,OFFSETFETCH子句可以以任何顺序出现在 PostgreSQL 中。

FETCH 对比 LIMIT

FETCH子句在功能上等同于LIMIT子句。如果您计划使您的应用程序与其他数据库系统兼容,则应该使用FETCH子句,因为它遵循 SQL 标准。

PostgreSQL FETCH 示例

以下语句使用 FETCH 子句查询按标题升序排列的第一部电影:

SELECT
    film_id,
    title
FROM
    film
ORDER BY
    title 
FETCH FIRST ROW ONLY;

输出:

 film_id |      title
---------+------------------
       1 | Academy Dinosaur
(1 row)

它相当于以下查询:

SELECT
    film_id,
    title
FROM
    film
ORDER BY
    title 
FETCH FIRST 1 ROW ONLY;

以下语句使用FETCH子句查询按标题排序的前五部电影:

SELECT
    film_id,
    title
FROM
    film
ORDER BY
    title 
FETCH FIRST 5 ROW ONLY;

输出:

 film_id |      title
---------+------------------
       1 | Academy Dinosaur
       2 | Ace Goldfinger
       3 | Adaptation Holes
       4 | Affair Prejudice
       5 | African Egg
(5 rows)

以下语句返回按标题排序的前五部电影之后的接下来的五部电影:

SELECT
    film_id,
    title
FROM
    film
ORDER BY
    title 
OFFSET 5 ROWS 
FETCH FIRST 5 ROW ONLY;

输出:

 film_id |      title
---------+------------------
       6 | Agent Truman
       7 | Airplane Sierra
       8 | Airport Pollock
       9 | Alabama Devil
      10 | Aladdin Calendar
(5 rows)

4. IN

IN 运算符语法

您可以在WHERE子句中使用IN运算符来检查某个值是否与值列表中的任何值匹配。

IN运算符的语法如下:

value IN (value1,value2,...)

如果value匹配列表中的任何值,即value1, value2, … ,则IN运算符返回 true。

值列表可以是文字值(如数字、字符串)列表,或者SELECT语句的结果,如下:

value IN (SELECT column_name FROM table_name);

括号内的查询称为子查询,它是嵌套在另一个查询中的查询。请注意,您将在后续教程中了解有关子查询的更多信息。

PostgreSQL IN 运算符示例

假设你想知道 ID 为 1 和 2 的客户的租赁信息,你可以在WHERE子句中使用IN运算符,如下所示:

SELECT customer_id,
rental_id,
return_date
FROM
rental
WHERE
customer_id IN (1, 2)
ORDER BY
return_date DESC;

以下查询使用等于 (=) 和OR运算符替代 IN 运算符。它等价于上面的查询:

SELECT
rental_id,
customer_id,
return_date
FROM
rental
WHERE
customer_id = 1 OR customer_id = 2
ORDER BY
return_date DESC;

使用IN运算符的查询比使用等于 (=) 和OR运算符的查询更短且更具可读性。此外,PostgreSQL 使用IN运算符执行查询比使用OR运算符列表执行相同查询要快得多。

PostgreSQL NOT IN 运算符

您可以将IN运算符与NOT运算符结合使用来选择其值与列表中的值不匹配的行。

例如,以下语句查找 ID 不为 1 或 2 的客户的所有租赁。

SELECT
customer_id,
rental_id,
return_date
FROM
rental
WHERE
customer_id NOT IN (1, 2);

IN运算符类似,您可以使用不等于 (<>) 和AND运算符来编写NOT IN运算符:

SELECT
customer_id,
rental_id,
return_date
FROM
rental
WHERE
customer_id <> 1
AND customer_id <> 2;

此查询返回与上面使用NOT IN运算符的查询相同的输出。

带有子查询的 IN 表达式

以下语句从rental表中查询返回日期为2005-05-27的客户 ID 列表:

SELECT customer_id
FROM rental
WHERE CAST (return_date AS DATE) = '2005-05-27'
ORDER BY customer_id;

由于此查询返回一个值列表,因此您可以将其用作IN运算符的输入,如下所示:

SELECT
customer_id,
first_name,
last_name
FROM
customer
WHERE
customer_id IN (
SELECT customer_id
FROM rental
WHERE CAST (return_date AS DATE) = '2005-05-27'
)
ORDER BY customer_id;

5. BETWEEN

BETWEEN 运算符简介

您可以使用BETWEEN运算符将一个值与一系列值进行匹配。下面说明了BETWEEN运算符的语法:

value BETWEEN low AND high;

如果value大等于low值且小等于high值,则表达式返回 true,否则返回 false。

您可以使用大等于 (>=) 或小等于 (<=) 运算符重写BETWEEN运算符,如下所示:

value >= low and value <= high

如果要检查值是否超出范围,可以将NOT运算符与BETWEEN运算符组合起来,如下所示:

value NOT BETWEEN low AND high;

以下表达式等效于使用NOTBETWEEN运算符的表达式:

value < low OR value > high

PostgreSQL BETWEEN 运算符示例

以下查询使用BETWEEN运算符选择金额在 8 到 9(美元)之间的付款:

SELECT
customer_id,
payment_id,
amount
FROM
payment
WHERE
amount BETWEEN 8 AND 9;

要获取金额不在 8 和 9 范围内的付款,请使用以下查询:

SELECT
customer_id,
payment_id,
amount
FROM
payment
WHERE
amount NOT BETWEEN 8 AND 9;

如果要检查日期范围内的值,则应使用 ISO 8601 格式的文字日期,即 YYYY-MM-DD。例如,要获取付款日期在2007-02-072007-02-15之间的付款,请使用以下查询:

SELECT
customer_id,
payment_id,
amount,
    payment_date
FROM
payment
WHERE
payment_date BETWEEN '2007-02-07' AND '2007-02-15';

6. LIKE

LIKE 运算符简介

假设您想要找到一位客户,但您不记得她的确切名字。但是,您可以记得她的名字以类似Jen开头。

如何从数据库中找到准确的客户?您可以通过查看名字列来查找customer表中的客户,看看是否有任何以Jen开头的值。但是,如果客户表包含大量行,则此过程可能会非常耗时。

幸运的是,您可以使用 PostgreSQL 的LIKE运算符,通过以下查询将客户的名字与字符串进行匹配:

SELECT
first_name,
    last_name
FROM
customer
WHERE
first_name LIKE 'Jen%';

请注意,其中WHERE子句包含一个特殊表达式:first_nameLIKE运算符和包含百分号 (%) 的字符串。字符串'Jen%'称为模式。

该查询返回first_name列值以Jen开头且后跟任意字符序列的行。这种技术称为模式匹配。

您可以通过将文字值与通配符组合来构造模式,并使用LIKENOT LIKE运算符来查找匹配项。PostgreSQL 为您提供了两个通配符:

  • 百分号 (%) 匹配任何零个或多个字符的序列。
  • 下划线符号 (_) 匹配任何单个字符。

PostgreSQL LIKE运算符的语法如下:

如果valuepattern匹配,则表达式返回 true。

要否定LIKE运算符,请按如下方式使用NOT运算符:

valuepattern不匹配时,NOT LIKE运算符返回 true。

如果模式不包含任何通配符,则LIKE运算符的行为类似于等于 (=) 运算符。

PostgreSQL LIKE 运算符 – 模式匹配示例

让我们看一些使用LIKE运算符的例子。

简单的 PostgreSQL LIKE 示例

请查看以下示例:

SELECT
'foo' LIKE 'foo', -- true
'foo' LIKE 'f%', -- true
'foo' LIKE '_o_', -- true
'bar' LIKE 'b_'; -- false

怎么运行的。

  • 第一个表达式返回 true,因为foo模式不包含任何通配符,因此该LIKE运算符的作用类似于等于 (=) 运算符。
  • 第二个表达式返回 true,因为它匹配以字母f开头且后跟任意数量的字符的任何字符串。
  • 第三个表达式返回 true,因为模式 (_o_) 匹配以任何单个字符开头、后跟字母o并以任何单个字符结尾的任何字符串。
  • 第四个表达式返回 false,因为模式b_与以字母开头b且后跟任何单个字符的任何字符串匹配。

可以在模式的开头和/或结尾使用通配符。

例如,以下查询返回名字包含er字符串的客户,比如JeniferKimberly等。

SELECT
first_name,
    last_name
FROM
customer
WHERE
first_name LIKE '%er%'
ORDER BY
    first_name;

您可以将百分号 (%) 与下划线 (_) 组合起来构建模式,如下例所示:

SELECT
first_name,
last_name
FROM
customer
WHERE
first_name LIKE '_her%'
ORDER BY 
        first_name;

模式_her%匹配任何符合以下条件的字符串:

  • 以任意单个字符 (_) 开头。
  • 后面跟着文字字符串her
  • 并且以任意数量的字符结尾。

返回的名字是 Cheryl、Sherri、Sherry 和 Therasa。

PostgreSQL NOT LIKE 示例

以下查询使用NOT LIKE运算符查找名字不以Jen开头的客户:

SELECT
first_name,
last_name
FROM
customer
WHERE
first_name NOT LIKE 'Jen%'
ORDER BY 
        first_name

PostgreSQL 对 LIKE 运算符的扩展

PostgreSQL 支持类似于LIKE运算符的ILIKE运算符。此外,ILIKE运算符匹配值时不区分大小写。例如:

SELECT
first_name,
last_name
FROM
customer
WHERE
first_name ILIKE 'BAR%';

在这里插入图片描述

模式BAR%匹配以BARBarBaR等开头的任何字符串。如果您改用LIKE运算符,查询将不会返回任何行。

PostgreSQL 还提供了一些类似于LIKE, NOT LIKE, ILIKENOT ILIKE的运算符,如下所示:

运算符等价于
~~LIKE
~~*ILIKE
!~~NOT LIKE
!~~*NOT ILIKE

7. IS NULL

NULL 和 IS NULL 运算符简介

在数据库世界中,NULL 意味着缺少信息或不适用。NULL 不是一个值,因此,您不能将它与任何其他值(例如数字或字符串)进行比较。NULL 与值的比较将始终得到 NULL,这意味着结果未知。

此外,NULL 不等于 NULL,因此以下表达式返回 NULL:

假设您有一个contacts表存储联系人的名字、姓氏、电子邮件和电话号码。在记录联系人时,您可能不知道联系人的电话号码。

为了解决这个问题,您可以将phone列定义为可为空列,并在保存联系人信息时将 NULL 插入到phone列中。

CREATE TABLE contacts(
    id INT GENERATED BY DEFAULT AS IDENTITY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(255) NOT NULL,
    phone VARCHAR(15),
    PRIMARY KEY (id)
);

如果执行CREATE TABLE语句时出现错误,您的 PostgreSQL 版本可能不支持标识列语法。在这种情况下,您可以使用以下语句:

CREATE TABLE contacts(
    id SERIAL,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(255) NOT NULL,
    phone VARCHAR(15),
    PRIMARY KEY (id)
);

以下语句插入两个联系人,一个有电话号码,另一个没有:

INSERT INTO contacts(first_name, last_name, email, phone)
VALUES ('John','Doe','john.doe@rockdata.net',NULL),
    ('Lily','Bush','lily.bush@rockdata.net','(408-234-2764)');

要查找没有电话号码的联系人,您可以使用以下语句:

SELECT
    id,
    first_name,
    last_name,
    email,
    phone
FROM
    contacts
WHERE
    phone = NULL;

该语句不返回任何行。这是因为WHERE子句中的表达式phone = NULL始终返回 false。

即使电话列中存在 NULL,表达式NULL = NULL也会返回 false。这是因为 NULL 不等于任何值,甚至它本身也不等于。

要检查值是否为 NULL,请使用IS NULL运算符:

如果值为 NULL,则表达式返回 true,否则返回 false。

因此,要获取电话列中没有存储任何电话号码的联系人,请使用以下语句:

SELECT
    id,
    first_name,
    last_name,
    email,
    phone
FROM
    contacts
WHERE
    phone IS NULL;

IS NOT NULL 运算符

要检查值是否不为 NULL,请使用IS NOT NULL运算符:

如果值不为 NULL,则表达式返回 true;如果值为 NULL,则表达式返回 false。

例如,要查找有电话号码的联系人,您可以使用以下语句:

SELECT
    id,
    first_name,
    last_name,
    email,
    phone
FROM
    contacts
WHERE
    phone IS NOT NULL;
  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值