sql算术运算符

At its core, the internet and all its applications are just data.

互联网及其所有应用程序的核心只是数据。

Every email, tweet, selfie, bank transaction, and more is just data sitting in a database somewhere.

每封电子邮件,推文,自​​拍照,银行交易等等,都只是数据存储在某个地方的数据库中。

For that data to be useful, we have to be able to retrieve it. However, just retrieving the data is not enough—the data also has to be useful and relevant to our situation.

为了使该数据有用,我们必须能够检索它。 但是,仅检索数据是不够的-数据必须有用并且与我们的情况相关。

At the database level, we request specific information from the database by writing a SQL query. This SQL query specifies the data we want to receive and the format we want to receive it in.

在数据库级别,我们通过编写SQL查询来请求数据库的特定信息 这个SQL查询指定我们要接受的数据格式,我们要接受进去。

In this article we'll look at all of the most common ways to filter a SQL query.

在本文中,我们将介绍所有用于过滤SQL查询的最常用方法。

Here's what we'll cover:

这是我们要介绍的内容:

  • Setting up your database

    设置数据库

  • Creating users

    建立使用者

  • Inserting users

    插入用户

  • Filtering data with WHERE

    使用WHERE过滤数据

  • Logical operators (AND / OR / NOT)

    逻辑运算符( AND / OR / NOT )

  • Comparison operators (<, >, <=, >=)

    比较运算符( <><=>= )

  • Arithmetic operators (+, -, *, /, %)

    算术运算符( +-*/% )

  • Existence operators (IN / NOT IN)

    存在运算符( IN / NOT IN )

  • Partial matching using LIKE

    使用LIKE部分匹配

  • Dealing with missing data (NULL)

    处理丢失的数据( NULL )

  • Using IS NULL and IS NOT NULL

    使用IS NULLIS NOT NULL

  • Comparison operators with dates and times

    比较日期和时间的运算符

  • Existence using EXISTS / NOT EXISTS

    使用EXISTS / NOT EXISTS存在

  • Bitwise operators

    按位运算符

  • Conclusion

    结论

设置数据库 (Setting up your database)

To filter our data, we first of course must have some.

要过滤我们的数据,我们当然首先必须要有一些。

For these examples we'll be using PostgreSQL, but the queries and concepts shown here will easily translate to any other modern database system (like MySQL, SQL Server, etc.).

对于这些示例,我们将使用PostgreSQL,但是此处显示的查询和概念将轻松转换为任何其他现代数据库系统(例如MySQL,SQL Server等)。

To work with our PostgreSQL database, we can use psql — the interactive PostgreSQL command line program. If you have another database client that you enjoy working with that's fine too!

要使用PostgreSQL数据库,我们可以使用psql —交互式PostgreSQL命令行程序。 如果您有另一个喜欢的数据库客户端,那也很好!

To begin, let's create our database. With PostgreSQL already installed, we can run the psql command createdb <database-name> at our terminal to create a new database. I called mine fcc:

首先,让我们创建数据库。 在已经安装了 PostgreSQL情况下,我们可以在终端上运行psql命令createdb <database-name>来创建新数据库。 我叫我的fcc

$ createdb fcc

Next let's start the interactive console by using the command psql and connect to the database we just made using \c <database-name>:

接下来,让我们使用命令psql启动交互式控制台,并使用\c <database-name>连接到我们刚建立的\c <database-name>

$ psql
psql (11.5)
Type "help" for help.john=# \c fcc
You are now connected to database "fcc" as user "john".
fcc=#

建立使用者 (Creating users)

Now that we have a database, let's create a database table to model a potential user in our fictional system.

现在我们有了一个数据库,让我们创建一个数据库表来为虚拟系统中的潜在用户建模。

We'll call this table users, and each row in this table will represent one of our users.

我们称此表为users ,此表中的每一行将代表我们的一个用户。

This users table will have columns that we would expect to describe a user — things like a name, email, and an age.

users表将包含我们希望描述用户的列,例如名称,电子邮件和年龄。

Inside our psql session let's create the users table:

在我们的psql会话中,我们创建users表:

CREATE TABLE users(id SERIAL PRIMARY KEY,first_name TEXT NOT NULL,last_name TEXT NOT NULL,email TEXT NOT NULL,age INTEGER NOT NULL
);

The output shows CREATE TABLE which means are table creation was successful.

输出显示CREATE TABLE ,这表示表创建成功。

Note: I've cleaned up the psql output in these examples to make it easier to read, so don't worry if the output shown here isn't exactly what you've seen in your terminal.

注意:在这些示例中,我已经清理了psql输出,以使其更易于阅读,因此请不要担心此处显示的输出与您在终端中看到的输出不完全相同。

Let's look at the contents of our users table:

让我们看一下我们的users表的内容:

SELECT * FROM users;id | first_name | last_name | email | age
----+------------+-----------+-------+-----
(0 rows)

We haven't inserted any data into our table, so we just see the empty table structure.

我们没有在表中插入任何数据,因此我们只看到空表结构。

If you aren't familiar with SQL queries, the one we just ran, SELECT * FROM users, is one of the simplest ones you can write.

如果您不熟悉SQL查询,那么我们刚运行的查询SELECT * FROM users是您可以编写的最简单的查询之一。

The keyword SELECT specifies which column(s) you want to return (* means "all columns"), and the FROM keyword specifies which table you want to select from (in this case users).

关键字SELECT指定要返回的列( *表示“所有列”),而FROM关键字指定要从哪个表中选择(本例中为users )。

So SELECT * FROM users really means return all rows and all columns from the users table.

因此, SELECT * FROM users确实意味着users表返回所有行和所有列。

If we wanted to return specific columns from the users table, we could replace SELECT * with the columns we want to return — for example SELECT id, name FROM users.

如果我们想从users表中返回特定的列,则可以将SELECT *替换为我们要返回的列,例如SELECT id, name FROM users

插入用户 (Inserting users)

An empty table isn't very interesting, so let's insert some data into our table so we can practice querying against it:

空表不是很有趣,因此让我们在表中插入一些数据,以便我们练习对它进行查询:

INSERT INTO users(first_name, last_name, email, age) VALUES
('John', 'Smith', 'johnsmith@gmail.com', 25),
('Jane', 'Doe', 'janedoe@Gmail.com', 28),
('Xavier', 'Wills', 'xavier@wills.io', 35),
('Bev', 'Scott', 'bev@bevscott.com', 16),
('Bree', 'Jensen', 'bjensen@corp.net', 42),
('John', 'Jacobs', 'jjacobs@corp.net', 56),
('Rick', 'Fuller', 'fullman@hotmail.com', 16);

If we run that insert statement in our psql session, we see the output INSERT 0 7. This means that we have successfully inserted 7 new rows into our table.

如果在psql会话中运行该insert语句, psql看到输出INSERT 0 7 。 这意味着我们已经成功地在表中插入了7个新行。

If we run our SELECT * FROM users query again, we'll now see that data:

如果再次运行SELECT * FROM users查询,现在将看到该数据:

SELECT * FROM users;id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Jacobs    | jjacobs@corp.net    |  562 | Rick       | Fuller    | fullman@hotmail.com |  163 | Bree       | Jensen    | bjensen@corp.net    |  424 | Bev        | Scott     | bev@bevscott.com    |  165 | Xavier     | Wills     | xavier@wills.io     |  356 | Jane       | Doe       | janedoe@Gmail.com   |  287 | John       | Smith     | johnsmith@gmail.com |  25
(7 rows)

使用WHERE过滤数据 (Filtering data with WHERE)

So far, we've just returned all of the rows from our table. This is the default behavior of the query. To return a more selective set of rows we need to filter the rows using a WHERE clause.

到目前为止,我们只返回了表中的所有行。 这是查询的默认行为。 要返回更具选择性的行集,我们需要使用WHERE子句过滤行。

There are many ways to filter our rows using a WHERE clause. The simplest operator we can use is the equality operator: =.

有多种方法可以使用WHERE子句过滤行。 我们可以使用的最简单的运算符是相等运算符: =

Say we wanted to find users whose first name was "John":

假设我们要查找名字为“ John”的用户:

SELECT *
FROM users
WHERE first_name = 'John';id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Jacobs    | jjacobs@corp.net    |  567 | John       | Smith     | johnsmith@gmail.com |  25
(2 rows)

Here we appended the keyword WHERE to our query followed by an equality statement: first_name = 'John'.

在这里,我们在查询中附加了关键字WHERE ,后跟一个相等性语句: first_name = 'John'

Our database first looks at the FROM keyword to determine what data to fetch. So, the database will read this query, see FROM users, and go and fetch all of the rows for the users table from the disk.

我们的数据库首先查看FROM关键字,以确定要提取的数据。 因此,数据库将读取此查询,请参见FROM users ,然后从磁盘中获取users表的所​​有行。

Once all of the rows have been retrieved from the users table, it then runs the WHERE clause against each row and only returns rows where the first_name column value equals "John."

一旦从users表中检索了所有行,它就对每行运行WHERE子句,并且仅返回first_name列值等于“ John”的行。

In our data, there are two rows that match that first name.

在我们的数据中,有两行与该名字匹配。

If we wanted to find a particular "John" in our system, we could query based on a column that we know is unique — like our id column.

如果我们想在系统中找到特定的“ John”,则可以基于已知唯一的列(例如我们的id列)进行查询。

To find the "John Jacobs" row specifically, we could query by his ID:

要专门查找“ John Jacobs”行,我们可以通过其ID查询:

SELECT *
FROM users
WHERE id = 1;id | first_name | last_name |      email       | age
----+------------+-----------+------------------+-----1 | John       | Jacobs    | jjacobs@corp.net |  56
(1 row)

Here only one record matched the condition of id = 1, so we only got back one row.

这里只有一条记录符合id = 1的条件,因此我们只返回了一行。

逻辑运算符( AND / OR / NOT ) (Logical operators (AND / OR / NOT))

We can filter by more than just the equality operator. We can also use the boolean logical operators that are found in most programming languages: and, or, and not.

我们不仅可以通过相等运算符进行筛选。 我们还可以使用大多数编程语言中的布尔逻辑运算符: 和,或和而不是

In many programming languages and and or are represented by && and ||. In SQL, they're simply AND and OR.

在许多编程语言中, andor&&||表示。 。 在SQL中,它们只是ANDOR

Instead of querying by ID, let's try to find the record for the person named "John Smith." To do this, we can use an AND in our WHERE clause to look for both the first name and last name condition:

让我们尝试查找名为“ John Smith”的人的记录,而不是通过ID进行查询。 为此,我们可以在WHERE子句中使用AND来查找名字和姓氏条件:

SELECT *
FROM users
WHERE first_name = 'John'AND last_name = 'Smith';id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----7 | John       | Smith     | johnsmith@gmail.com |  25
(1 row)

To find people with a first name of "John" or a last name of "Doe":

查找姓氏为“ John” 姓氏为“ Doe”的人:

SELECT *
FROM users
WHERE first_name = 'John'OR last_name = 'Doe';id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Jacobs    | jjacobs@corp.net    |  566 | Jane       | Doe       | janedoe@Gmail.com   |  287 | John       | Smith     | johnsmith@gmail.com |  25
(3 rows)

Here our result contained both Johns as well as Jane Doe.

在这里,我们的结果既包含Johns也包含Jane Doe

These AND and OR conditions can also be chained together. Let's say we wanted to find someone named exactly "John Smith", or someone with a last name of "Doe":

这些ANDOR条件也可以链接在一起。 假设我们想找到一个名字叫“ John Smith”的人, 或者姓“ Doe”的人:

SELECT *
FROM users
WHERE
(first_name = 'John'AND last_name = 'Smith'
)
OR last_name = 'Doe';id | first_name  | last_name |        email        | age
----+------------+-----------+---------------------+-----6 | Jane       | Doe       | janedoe@Gmail.com   |  287 | John       | Smith     | johnsmith@gmail.com |  25
(2 rows)

If we wanted to invert this condition and find users who are not named "John Smith" and also do not have a last name of "Doe", we could add the NOT operator:

如果我们想反转此条件并查找命名为“ John Smith”且也没有姓氏“ Doe”的用户,则可以添加NOT运算符:

SELECT *
FROM users
WHERE NOT
((first_name = 'John'AND last_name = 'Smith')OR last_name = 'Doe'
);id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----4 | Bev        | Scott     | bev@bevscott.com    |  165 | Bree       | Jensen    | bjensen@corp.net    |  426 | John       | Jacobs    | jjacobs@corp.net    |  567 | Rick       | Fuller    | fullman@hotmail.com |  163 | Xavier     | Wills     | xavier@wills.io     |  35
(5 rows)

Note: everyone has their own personal style of how they like to format queries — do whatever makes sense to you!

注意:每个人都有自己喜欢的格式查询样式-做对您有意义的一切!

比较运算符( <><=>= ) (Comparison operators (<, >, <=, >=))

Similar to other programming languages, SQL also the comparison operators: <, >, <=, >=.

与其他编程语言类似,SQL也是比较运算符: <><=>=

Let's practice using these operators against our users' age column.

让我们针对用户的age列练习使用这些运算符。

Let's say we wanted to find users that were eighteen years or older:

假设我们要查找18岁以上的用户

SELECT * FROM users WHERE age >= 18;id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Jacobs    | jjacobs@corp.net    |  563 | Bree       | Jensen    | bjensen@corp.net    |  425 | Xavier     | Wills     | xavier@wills.io     |  356 | Jane       | Doe       | janedoe@Gmail.com   |  287 | John       | Smith     | johnsmith@gmail.com |  25
(5 rows)

What about users that are older than 25, but less than or equal to 35 years old?

25岁以上但小于等于35岁的用户呢?

SELECT * FROM users WHERE age > 25 AND age <= 35;id | first_name | last_name |       email       | age
----+------------+-----------+-------------------+-----5 | Xavier     | Wills     | xavier@wills.io   |  356 | Jane       | Doe       | janedoe@Gmail.com |  28
(2 rows)

算术运算符( +-*/% ) (Arithmetic operators (+, -, *, /, %))

We can also perform mathematical calculations on our data.

我们还可以对数据进行数学计算。

Our users table has an age column, what if we wanted to find half of each person's age?

我们的users表中有一个age列,如果我们想找到每个人年龄的一半怎么办?

SELECT*,age / 2 AS half_of_their_age
FROM users;id | first_name | last_name |        email        | age | half_of_their_age
----+------------+-----------+---------------------+-----+-------------------1 | John       | Jacobs    | jjacobs@corp.net    |  56 |                282 | Rick       | Fuller    | fullman@hotmail.com |  16 |                 83 | Bree       | Jensen    | bjensen@corp.net    |  42 |                214 | Bev        | Scott     | bev@bevscott.com    |  16 |                 85 | Xavier     | Wills     | xavier@wills.io     |  35 |                176 | Jane       | Doe       | janedoe@Gmail.com   |  28 |                147 | John       | Smith     | johnsmith@gmail.com |  25 |                12
(7 rows)

Here we select all of the table columns (using SELECT *), and we also select a new aggregate calculation: age / 2. We also give this value a descriptive name (half_of_their_age) with an alias using the AS keyword.

在这里,我们选择所有表列(使用SELECT * ),并且还选择一个新的汇总计算: age / 2 。 我们还使用AS关键字为该值提供一个具有别名的描述性名称( half_of_their_age )。

We can also find who's age is an even number by using the modulus or remainder operator (%):

我们还可以通过使用模或余数运算符( % )来查找谁的年龄是偶数

SELECT * FROM users WHERE (age % 2) = 0;id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Jacobs    | jjacobs@corp.net    |  562 | Rick       | Fuller    | fullman@hotmail.com |  163 | Bree       | Jensen    | bjensen@corp.net    |  424 | Bev        | Scott     | bev@bevscott.com    |  166 | Jane       | Doe       | janedoe@Gmail.com   |  28
(5 rows)

We can find who's age is an odd number by changing our = condition to a "not equals" using != or <>:

通过使用!=<>将我们的=条件更改为“不等于”,可以发现谁的年龄是一个奇数

SELECT * FROM users WHERE (age % 2) <> 0;id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----5 | Xavier     | Wills     | xavier@wills.io     |  357 | John       | Smith     | johnsmith@gmail.com |  25
(2 rows)

存在运算符( IN / NOT IN ) (Existence operators (IN / NOT IN))

If we wanted to check that a column value existed in a list of values, we can use IN or NOT IN:

如果要检查值列表中是否存在列值,可以使用INNOT IN

SELECT *
FROM users
WHERE first_name IN ('John', 'Jane', 'Rick');id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Smith     | johnsmith@gmail.com |  252 | Jane       | Doe       | janedoe@Gmail.com   |  286 | John       | Jacobs    | jjacobs@corp.net    |  567 | Rick       | Fuller    | fullman@hotmail.com |  16
(4 rows)

Similarly, we can use NOT IN to negate that condition:

同样,我们可以使用NOT IN否定该条件:

SELECT *
FROM users
WHERE first_name NOT IN ('John', 'Jane', 'Rick');id | first_name | last_name |      email       | age
----+------------+-----------+------------------+-----3 | Xavier     | Wills     | xavier@wills.io  |  354 | Bev        | Scott     | bev@bevscott.com |  165 | Bree       | Jensen    | bjensen@corp.net |  42
(3 rows)

使用LIKE部分匹配 (Partial matching using LIKE)

Sometimes, we may want to search for rows based on a partial-search.

有时,我们可能希望基于部分搜索来搜索行。

Say for example we wanted to find all users that signed up for our application using a Gmail address. We can do a partial match against a column using the LIKE keyword. We can also specify a wildcard (or "match anything") in the match string using %.

例如,我们要查找使用Gmail地址注册了我们的应用程序的所有用户。 我们可以使用LIKE关键字对列进行部分匹配。 我们还可以使用%在匹配字符串中指定通配符(或“匹配所有内容”)。

To find users with an email that ends in gmail.com:

要查找电子邮件以gmail.com结尾的用户:

SELECT *
FROM users
WHERE email LIKE '%gmail.com';id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Smith     | johnsmith@gmail.com |  25
(1 row)

The string %gmail.com means "match anything that ends in gmail.com."

字符串%gmail.com意思是“匹配以gmail.com结尾的任何内容。”

If we look back at our users data, we'll notice that we actually have two users with a gmail.com address:

如果回头看我们的用户数据,我们会发现实际上有两个用户的gmail.com地址:

('John', 'Smith', 'johnsmith@gmail.com', 25),
('Jane', 'Doe', 'janedoe@Gmail.com', 28),

However, Jane's email has a capital "G' in her email address. Or previous query didn't pick up this record because it was matching exactly against gmail.com with a lowercase "g."

但是,Jane的电子邮件地址中的电子邮件首字母大写为“ G”,否则以前的查询未选择此记录,因为它与gmail.com 完全匹配,但小写字母为“ g”。

To do a case-insensitive match, we just need to substitute LIKE for ILIKE:

要进行不区分大小写的匹配,我们只需要用LIKE代替ILIKE

SELECT *
FROM users
WHERE email ILIKE '%gmail.com';id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Smith     | johnsmith@gmail.com |  252 | Jane       | Doe       | janedoe@Gmail.com   |  28
(2 rows)

The wildcard symbol % at the beginning of the string means anything that ends in "gmail.com" will be returned. That could be bob.jones+12345@gmail.com or asdflkasdflkj@gmail.com — as long as it ends in gmail.com.

字符串开头的通配符%表示将返回以“ gmail.com”结尾的任何内容。 可以是bob.jones+12345@gmail.comasdflkasdflkj@gmail.com只要以gmail.com结尾即可。

We can also add as many wildcards (%) as we want.

我们还可以根据需要添加任意多个通配符( % )。

For example, the search term %j%o% will return any emails that follow the pattern <anything> followed by a j, followed by <anything>, followed by an o, followed by <anything>:

例如,搜索词%j%o%将返回所有遵循以下格式的电子邮件: <anything>模式,后跟j ,后跟<anything> ,然后是o ,然后是<anything>

SELECT * FROM users WHERE email ILIKE '%j%o%';id | first_name | last_name |        email        | age
----+------------+-----------+---------------------+-----1 | John       | Smith     | johnsmith@gmail.com |  252 | Jane       | Doe       | janedoe@Gmail.com   |  285 | Bree       | Jensen    | bjensen@corp.net    |  426 | John       | Jacobs    | jjacobs@corp.net    |  56
(4 rows)

处理丢失的数据( NULL ) (Dealing with missing data (NULL))

Next let's look at how we deal with rows with columns that have missing data.

接下来,让我们看看如何处理包含缺少数据的列的行。

To do that, let's add another column to our users table: first_paid_at.

为此,让我们在users表中添加另一列: first_paid_at

This new column will be a TIMESTAMP (similar to a datetime in other languages), and it will represent the first date and time that a user paid us money for our application. Maybe we want to send them a nice card or some flowers on the anniversary of using our app?

这种新列将是一个TIMESTAMP (类似于datetime在其他语言),这将代表第一日期和时间,用户支付我们的钱为我们的应用程序。 也许我们想在使用我们的应用程序周年纪念日给他们发送精美的卡片或一些鲜花?

We could drop our users table using DROP TABLE users; and re-create it, but that would also delete all of the data in our table.

我们可以使用DROP TABLE users;删除usersDROP TABLE users; 并重新创建它,但这也会删除表中的所有数据。

To change a table without dropping it and losing the data, we can use ALTER TABLE:

要更改表而不删除它并丢失数据,我们可以使用ALTER TABLE

ALTER TABLE users ADD COLUMN first_paid_at TIMESTAMP;

That command returns the result ALTER TABLE, so our ALTER query succeeded.

该命令返回结果ALTER TABLE ,因此我们的ALTER查询成功。

If we query our users table now, we'll notice that this new column doesn't have any data in it:

如果现在查询users表,我们会注意到此新列中没有任何数据:

SELECT * FROM users;id | first_name | last_name |        email        | age | first_paid_at
----+------------+-----------+---------------------+-----+---------------1 | John       | Smith     | johnsmith@gmail.com |  25 |2 | Jane       | Doe       | janedoe@Gmail.com   |  28 |3 | Xavier     | Wills     | xavier@wills.io     |  35 |4 | Bev        | Scott     | bev@bevscott.com    |  16 |5 | Bree       | Jensen    | bjensen@corp.net    |  42 |6 | John       | Jacobs    | jjacobs@corp.net    |  56 |7 | Rick       | Fuller    | fullman@hotmail.com |  16 |
(7 rows)

Our first_paid_at column is empty, and the result from our psql query shows it as an empty column. This column is not technically empty — it contains a special value that psql is choosing not to display in its output: NULL.

我们的first_paid_at空,而psql查询的结果将其显示为空列。 该列从技术上讲不是空的-它包含psql选择不在其输出中显示的特殊值: NULL

NULL is a special value in databases. It's the absence or lack of a value, and it doesn't behave as we expect it would.

NULL是数据库中的特殊值。 是缺少或缺少值,并且它的行为不像我们期望的那样。

To illustrate this, let's look at the simple SELECT statements below:

为了说明这一点,让我们看一下下面的简单SELECT语句:

SELECT1 = 1,1 = 2;?column? | ?column?
----------+----------t        | f
(1 row)

Here we simply selected 1 = 1 and 1 = 2. As we expect, the result of these two statements is t and f (or TRUE and FALSE). 1 is equal to 1, and 1 is not equal to 2.

在这里,我们仅选择1 = 11 = 2 。 正如我们期望的那样,这两个语句的结果是tf (或TRUEFALSE )。 1等于1 ,而1不等于2

Now let's try the same with NULL:

现在让我们尝试使用NULL

SELECT 1 = NULL;?column?
----------(1 row)

We might expect this value to be FALSE, but the return value is actually NULL.

我们可能希望此值为FALSE ,但返回值实际上为NULL

To visualize these NULLs a little better, let's set how psql displays NULL values using the \pset option:

为了更好地显示这些NULL ,让我们使用\pset选项设置psql如何显示NULL值:

fcc=# \pset null 'NULL'
Null display is "NULL".

Now if we run that query again we'll see the NULL output we expect:

现在,如果再次运行该查询,我们将看到期望的NULL输出:

SELECT 1 = NULL;?column?
----------NULL
(1 row)

So 1 is not equal to NULL, what about NULL = NULL?

所以1不等于NULL ,那么NULL = NULL呢?

SELECT NULL = NULL;?column?
----------NULL
(1 row)

Oddly enough, NULL is not equal to NULL.

奇怪的是, NULL不等于NULL

It helps to think of NULL as an unknown value. Is an unknown value equal to 1? Well, we don't know — it's unknown. Is an unknown value equal to an unknown value? Again, it's unknown. In this way NULL makes a little more sense.

有助于将NULL视为未知值。 未知值等于1吗? 好吧,我们不知道-这是未知的。 未知值等于未知值吗? 同样,这是未知的。 这样, NULL更有意义。

使用IS NULLIS NOT NULL (Using IS NULL and IS NOT NULL)

We can't use the equality operator with NULL, but we can use two operators specifically designed for it: IS NULL and IS NOT NULL.

我们不能将相等运算符与NULL ,但是可以使用两个专门为它设计的运算符: IS NULLIS NOT NULL

SELECTNULL IS NULL,NULL IS NOT NULL;?column? | ?column?
----------+----------t        | f
(1 row)

These values come out as expect: NULL IS NULL is true, and NULL IS NOT NULL is false.

这些值按预期出现: NULL IS NULL是true,而NULL IS NOT NULL是false。

That's all fine and weird, but how do we use this?

很好,很奇怪,但是我们怎么使用呢?

Well first let's get some data in our first_paid_at column:

好吧,首先让我们在first_paid_at列中获取一些数据:

UPDATE users SET first_paid_at = NOW() WHERE id = 1;
UPDATE 1UPDATE users SET first_paid_at = (NOW() - INTERVAL '1 month') WHERE id = 2;
UPDATE 1UPDATE users SET first_paid_at = (NOW() - INTERVAL '1 year') WHERE id = 3;
UPDATE 1

In those UPDATE statements above we've set three different users first_paid_at columns: User ID 1 to the current time (NOW()), User ID 2 to one month ago, and User ID 3 to one year ago.

在上面的那些UPDATE语句中,我们将三个不同的用户first_paid_at列设置为:用户ID 1设置为当前时间( NOW() ),用户ID 2设置为一个月前,用户ID 3设置为一年前。

First, let's find users that have paid us and users who haven't:

首先,让我们找到已付款的用户和未付款的用户:

SELECT *
FROM users
WHERE first_paid_at IS NULL;id | first_name | last_name |        email        | age | first_paid_at
----+------------+-----------+---------------------+-----+---------------4 | Bev        | Scott     | bev@bevscott.com    |  16 | NULL5 | Bree       | Jensen    | bjensen@corp.net    |  42 | NULL6 | John       | Jacobs    | jjacobs@corp.net    |  56 | NULL7 | Rick       | Fuller    | fullman@hotmail.com |  16 | NULL
(4 rows)SELECT *
FROM users
WHERE first_paid_at IS NOT NULL;id | first_name | last_name |        email        | age |       first_paid_at
----+------------+-----------+---------------------+-----+----------------------------1 | John       | Smith     | johnsmith@gmail.com |  25 | 2020-08-11 20:49:17.2305172 | Jane       | Doe       | janedoe@Gmail.com   |  28 | 2020-07-11 20:49:17.2331243 | Xavier     | Wills     | xavier@wills.io     |  35 | 2019-08-11 20:49:17.23488
(3 rows)

比较日期和时间的运算符 (Comparison operators with dates and times)

Now that we have some data, let's use our same comparison operators against this new TIMESTAMP field.

现在我们有了一些数据,让我们对这个新的TIMESTAMP字段使用相同的比较运算符。

Let's try to find users that paid us for the first within the past week. To do this, we can take the current time, NOW(), and subtract from it one week using the INTERVAL keyword:

让我们尝试寻找在过去一周内首次向我们付款的用户。 为此,我们可以使用当前时间NOW() ,并使用INTERVAL关键字从中减去一个星期:

SELECT *
FROM users
WHERE first_paid_at > (NOW() - INTERVAL '1 week');id | first_name | last_name |        email        | age |       first_paid_at
----+------------+-----------+---------------------+-----+----------------------------1 | John       | Smith     | johnsmith@gmail.com |  25 | 2020-08-11 20:49:17.230517
(1 row)

We could also use a different interval, such as three months ago:

我们还可以使用其他时间间隔,例如三个月前:

SELECT *
FROM users
WHERE first_paid_at < (NOW() - INTERVAL '3 months');id | first_name | last_name |      email      | age |       first_paid_at
----+------------+-----------+-----------------+-----+---------------------------3 | Xavier     | Wills     | xavier@wills.io |  35 | 2019-08-11 20:49:17.23488
(1 row)

Let's try to find users that first paid us between one to six months ago.

让我们尝试寻找在1至6个月前首次向我们付款的用户。

We could combine our conditions again using AND, but instead of using less than and greater than operators let's use the BETWEEN keyword:

我们可以使用AND再次组合条件,但我们使用BETWEEN关键字代替使用小于大于运算符:

SELECT *
FROM users
WHERE first_paid_at BETWEEN (NOW() - INTERVAL '6 month')AND (NOW() - INTERVAL '1 month');id | first_name | last_name |       email       | age |       first_paid_at
----+------------+-----------+-------------------+-----+----------------------------2 | Jane       | Doe       | janedoe@Gmail.com |  28 | 2020-07-11 20:49:17.233124
(1 row)

使用EXISTS / NOT EXISTS存在 (Existence using EXISTS / NOT EXISTS)

Another way to check for existence is to use EXISTS and NOT EXISTS.

另一种检查是否存在的方法是使用EXISTSNOT EXISTS

These operators filter out rows by checking for the existence (or non-existence) of a condition. This condition is usually a query against another table.

这些运算符通过检查条件的存在(或不存在)来过滤出行。 此条件通常是针对另一个表的查询。

To set this up, let's create a new table called posts. This table will hold posts that a user can make in our system.

要进行设置,我们创建一个名为posts的新表。 该表将保存用户可以在我们的系统中发布的帖子。

CREATE TABLE posts(id SERIAL PRIMARY KEY,body TEXT NOT NULL,user_id INTEGER REFERENCES users NOT NULL
);

It's a simple table. It only contains an ID, a field to store the post text (body), and a reference to the user that wrote the post (user_id).

这是一张简单的桌子。 它仅包含一个ID,一个用于存储帖子文本的字段( body )和对撰写该帖子的用户的引用( user_id )。

Let's insert some data into this new table:

让我们在此新表中插入一些数据:

INSERT INTO posts(body, user_id) VALUES
('Here is post 1', 1),
('Here is post 2', 1),
('Here is post 3', 2),
('Here is post 4', 3);

In the data that we inserted into the posts table, User ID 1 has two posts, User ID 2 has one post, and User ID 3 also has one post.

在我们插入到posts表中的数据中,用户ID 1有两个帖子,用户ID 2有一个帖子,用户ID 3也有一个帖子。

To find users that do have posts, we can use EXISTS.

要查找确实有帖子的用户,我们可以使用EXISTS

The EXISTS keyword takes a subquery. If anything is returned from that subquery (even a row with just the value of NULL), the database will include that row in the result set.

EXISTS关键字接受一个子查询。 如果该子查询返回了任何内容 (甚至是只有NULL值的行),则数据库将在结果集中包括该行。

From the PostgreSQL docs on EXISTS:

来自 EXISTS上的PostgreSQL文档 :

The argument of EXISTS is an arbitrary SELECT statement, or subquery. The subquery is evaluated to determine whether it returns any rows. If it returns at least one row, the result of EXISTS is “true”; if the subquery returns no rows, the result of EXISTS is “false”.

EXISTS的参数是任意的SELECT语句或子查询。 评估子查询以确定它是否返回任何行。 如果返回至少一行,则EXISTS的结果为“ true”; 如果子查询不返回任何行,则EXISTS的结果为“ false”。

EXISTS is just looking for the existence of a row from the subquery — it doesn't matter what's in it.

EXISTS只是从子查询中寻找行的存在 -里面的内容无关紧要。

Here's an example of users that have posts using EXISTS:

这是一个使用EXISTS发布帖子的用户的示例:

SELECT *
FROM users
WHERE EXISTS (SELECT 1FROM postsWHERE posts.user_id = users.id
);id | first_name | last_name |        email        | age |       first_paid_at
----+------------+-----------+---------------------+-----+----------------------------1 | John       | Smith     | johnsmith@gmail.com |  25 | 2020-08-11 20:49:17.2305172 | Jane       | Doe       | janedoe@Gmail.com   |  28 | 2020-07-11 20:49:17.2331243 | Xavier     | Wills     | xavier@wills.io     |  35 | 2019-08-11 20:49:17.23488
(3 rows)

As we expected we got back User 1, 2, and 3.

如我们所料,我们重新获得了用户1、2和3。

Our EXISTS subquery is checking for a posts record where the post's user_id matches the id column on the users table. We returned 1 in our SELECT because we can return anything here—the database just wants to see that something was in fact returned.

我们的EXISTS子查询正在检查posts记录,其中帖子的user_idusers表上的id列匹配。 我们在SELECT返回1是因为我们可以在此处返回任何内容-数据库只想查看实际上已返回的内容。

Similarly, we could find users that don't have any posts by changing EXISTS to NOT EXISTS:

同样,我们可以通过将EXISTS更改为NOT EXISTS来查找没有帖子的用户:

SELECT *
FROM users
WHERE NOT EXISTS (SELECT 1FROM postsWHERE posts.user_id = users.id
);id | first_name | last_name |        email        | age | first_paid_at
----+------------+-----------+---------------------+-----+---------------4 | Bev        | Scott     | bev@bevscott.com    |  16 | NULL5 | Bree       | Jensen    | bjensen@corp.net    |  42 | NULL6 | John       | Jacobs    | jjacobs@corp.net    |  56 | NULL7 | Rick       | Fuller    | fullman@hotmail.com |  16 | NULL
(4 rows)

Finally, we could also re-write this query to use IN or NOT IN instead of EXISTS or NOT EXISTS, like this:

最后,我们还可以重写此查询以使用INNOT IN代替EXISTSNOT EXISTS ,如下所示:

SELECT *
FROM users
WHERE users.id IN (SELECT user_idFROM posts
);

This technically works, but as a general rule if you are testing for existence of another record it is generally more performant to use EXISTS. The IN and NOT IN operator are generally better used for checking a value against a static list like we did earlier:

从技术上讲这是可行的,但是作为一般规则,如果要测试是否存在另一条记录, 通常使用EXISTS 更有性能。 像我们之前所做的那样,通常最好使用INNOT IN运算符根据静态列表检查值:

SELECT *
FROM users
WHERE first_name IN ('John', 'Jane', 'Rick');

按位运算符 (Bitwise operators)

Although in practice the bitwise operators are not often used, for completeness let's look at a simple example.

尽管在实践中并不经常使用按位运算符,但是为了完整起见,让我们看一个简单的示例。

If we wanted to (for some reason) look at the age of our users in binary and play with flipping those bits around, we could use a variety of bitwise operators.

如果我们(出于某种原因)想要以二进制查看用户的年龄并玩转这些位,则可以使用各种按位运算符。

As an example, let's look at the bitwise "and" operator: &.

例如,让我们看一下按位“和”运算符: &

SELECT age::bit(8) & '11111111' FROM users;?column?
----------00010000001010100011100000010000000110010001110000100011
(7 rows)

To perform a bitwise calculation we first have to convert our age column from an integer to binary — in this example we cast it into an eight-bit binary string using ::bit(8).

要执行按位计算,我们首先必须将age列从整数转换为二进制-在本示例中,我们使用::bit(8)将其转换为八位二进制字符串。

Next we can "and" the result of our age in binary format with another binary string, 11111111.  Since a binary AND only returns 1 if both bits are 1's, this all 1's string keeps the output interesting.

接下来,我们可以使用另一个二进制字符串11111111以二进制格式“和”我们年龄的结果。 由于二进制AND仅在两个位均为1时才返回1,因此所有1的字符串都使输出有趣。

Almost every other bitwise operator uses the same format:

几乎所有其他按位运算符都使用相同的格式:

SELECT age::bit(8) | '11111111' FROM users;    -- bitwise OR
SELECT age::bit(8) # '11111111' FROM users;    -- bitwise XOR
SELECT age::bit(8) << '00000001' FROM users;   -- bitwise shift left
SELECT age::bit(8) >> '00000001' FROM users;   -- bitwise shift right

The bitwise "not" operator (~) is a little different in that it is applied to a single term — similar to the regular NOT operator:

按位的“非”运算符( ~ )有点不同,因为它应用于单个术语–类似于常规的NOT运算符:

SELECT ~age::bit(8) FROM users;?column?
----------11101111110101011100011111101111111001101110001111011100
(7 rows)

And finally, the most useful of the bitwise operators: concatenation.

最后,最有用的按位运算符:串联。

A common use of this operator is to combine strings of text together. For example if we wanted to build a calculated property of a "full name" for users, we could use concatenation:

此运算符的常见用法是将文本字符串组合在一起。 例如,如果我们想为用户构建一个“全名”的计算属性,则可以使用串联:

SELECT first_name || ' ' || last_name AS name
FROM users;name
--------------Bev ScottBree JensenJohn JacobsRick FullerJohn SmithJane DoeXavier Wills
(7 rows)

Here we concatenate (or "combine") the first_name, a space (' '), and the last_name property to build a name value.

在这里,我们将first_name ,一个空格( ' ' )和last_name属性连接(或“组合”)以构建name值。

结论 (Conclusion)

So that's an overview of basically every query filtering operator you'll ever need to use!

因此,这基本上是您需要使用的每个查询过滤运算符的概述!

There are a few more operators that we didn't cover here, but those operators are either not used very often or are used in exactly the same way as above—so they shouldn't pose you any trouble.

这里没有涉及更多的运算符,但是这些运算符要么不经常使用,要么以与上述完全相同的方式使用-因此它们不会给您带来麻烦。

If you liked this post, I write similar things on my blog here.

如果您喜欢这篇文章,我会在这里的博客上写下类似的内容。

Thanks for reading!

谢谢阅读!

John

约翰

翻译自: https://www.freecodecamp.org/news/sql-operators-tutorial/

sql算术运算符

sql算术运算符_SQL运算符教程–按位,比较,算术和逻辑运算符查询示例相关推荐

  1. sql运算符_SQL运算符

    sql运算符 SQL Operators are a series of characters, symbols and words which are used as part of the WHE ...

  2. sql算术运算符_SQL中的算术运算符

    sql算术运算符 SQL | 算术运算符 (SQL | Arithmetic Operators) Different number-crunching administrators are util ...

  3. 在学习Python基础中需要知道的知识点:运算符大全,收藏,以后方面查询(算术运算符、赋值运算符、比较运算符、位运算符、逻辑运算符、成员运算符、身份运算符、运算符优先级))

    一.算术运算符 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 30 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 -10 * 乘 - 两个数相乘或是返回一个被 ...

  4. C++ 笔记(10)— 运算符(算术、关系、逻辑、位运算、赋值和其它运算符)

    运算符是一种告诉编译器执行特定的数学或逻辑操作的符号. C++ 内置了丰富的运算符,并提供了以下类型的运算符: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其它运算符 1. 算术运算符 ...

  5. SQL基础学习总结:3(select语句基础算术运算符比较运算符)

    select语句基础 列的查询 从表中选取数据时需要使用select语句,通过select语句查询并选取出必要数据的过程称为匹配查询或查询. 语法结构如下: select <列名1>,&l ...

  6. 【算术、关系、逻辑、位、复合赋值、带副作用的、自增、自减、其它】运算符(学习笔记4--C语言运算符)

    前言: 如果你正在学习C语言而又不知道从何处开始学,你可以跟着我一起学习C语言,在寒假期间我每天都会发一篇博客,里面有各种C语言的知识点,如果你想学习下去,想进步,就来每天跟着我一起打卡吧,期待我们能 ...

  7. scala运算符_Scala运算符–算术,关系,逻辑,按位,赋值

    scala运算符 Today we will look into various types of scala operator. An operator tells the compiler to ...

  8. sql server运算符_SQL Server执行计划中SELECT运算符的主要概念

    sql server运算符 One of the main responsibilities of a database administrator is query tuning and troub ...

  9. sql 运算符_了解SQL ANY和ALL运算符

    sql 运算符 Hello, folks! Hope you all are doing well. In this article, we will be discussing about SQL ...

最新文章

  1. 在Python中连接字符串的首选方法是什么?
  2. 软件架构的相关概念小汇
  3. python三:if...else
  4. BZOJ1001 狼抓兔子
  5. virtual function的一些心得
  6. PHP header函数大全
  7. 新手坐高铁怎么找车厢_一个新手怎么做直播卖衣服?找对货源供应商成功一半...
  8. android intent enum,enum类型被intent所携带时需要注意的地方
  9. 吴恩达机器学习学习笔记第六章:机器学习中的线性代数操作python3版(含numpy、panda库的使用)
  10. docker容器的使用
  11. mysql tee_MySQL 使用tee记录语句和输出日志
  12. 调整home和根分区大小
  13. 有名内部类和匿名内部类的用法
  14. linux搭建vsftp服务器_Linux(CentOS 7)搭建VSFTP服务器
  15. J2EE 第二阶段项目之JUnit4进行单元测试(五)
  16. 迅雷,暴风影音,QQ这些软件是什么工具和语言编的?
  17. 老米之家 抢注域名应该怎么抢?抢注域名的价值如何去衡量
  18. FineBI产品简介
  19. PCL——简单点云可视化
  20. linux配置文件密码加密工具,Linux下利用openssl对文件进行加密和解密

热门文章

  1. 【java】兴唐第12-14节笔记整理
  2. docker 安装和使用
  3. python之抽象基类
  4. 2017年9月11日 梁勇 java教材 编程练习题 第二章 2.15 键盘 读取两个点的坐标值(小数),控制台输出两点间距离。...
  5. phpcms_v9修改文章会提示 [hash]数据验证失败
  6. 图像处理工具包ImagXpress的多页TIFF编辑API的使用(1)
  7. 热更新 FrameWork
  8. MYSQL 查询数据排序数据和分组数据
  9. iOS progressive Web App (PWA) 技术
  10. Elasticsearch6.1.3 for CRUD