15.4. Lesson: 查询

当您编写一个 SELECT ... 命令通常被称为查询--您在数据库中查询信息。

The goal of this lesson: 学习如何创建将返回有用信息的查询。

备注

如果您在上一课中没有这样做,请将以下人员对象添加到您的 people 桌子。如果收到任何与外键约束相关的错误,则需要首先将‘Main Road’对象添加到街道表中

insert into people (name,house_no, street_id, phone_no)
          values ('Joe Bloggs',3,2,'072 887 23 45');
insert into people (name,house_no, street_id, phone_no)
          values ('Jane Smith',55,3,'072 837 33 35');
insert into people (name,house_no, street_id, phone_no)
          values ('Roger Jones',33,1,'072 832 31 38');
insert into people (name,house_no, street_id, phone_no)
          values ('Sally Norman',83,1,'072 932 31 32');

15.4.1. 排序结果

让我们检索一个按门牌号排序的人员列表:

select name, house_no from people order by house_no;

结果:

     name     | house_no
--------------+----------
 Joe Bloggs   |        3
 Roger Jones  |       33
 Jane Smith   |       55
 Sally Norman |       83
(4 rows)

您可以按多个列的值对结果进行排序:

select name, house_no from people order by name, house_no;

结果:

     name     | house_no
--------------+----------
 Jane Smith   |       55
 Joe Bloggs   |        3
 Roger Jones  |       33
 Sally Norman |       83
(4 rows)

15.4.2. 过滤

通常,您不希望看到数据库中的每一条记录--尤其是如果有数千条记录,而您只对查看一两条记录感兴趣。

下面是一个数值过滤器的示例,它只返回以下对象 house_no 小于50:

select name, house_no from people where house_no < 50;

      name     | house_no
  -------------+----------
   Joe Bloggs  |        3
   Roger Jones |       33
  (2 rows)

您可以组合筛选器(使用 WHERE 子句)和排序(使用 ORDER BY 第(1)款):

select name, house_no from people where house_no < 50 order by house_no;

      name     | house_no
  -------------+----------
   Joe Bloggs  |        3
   Roger Jones |       33
  (2 rows)

您还可以基于文本数据进行筛选:

select name, house_no from people where name like '%s%';

      name     | house_no
  -------------+----------
   Joe Bloggs  |        3
   Roger Jones |       33
  (2 rows)

在这里,我们使用 LIKE 子句来查找所有带有 s 穿着它们。您将注意到该查询区分大小写,因此 Sally Norman 参赛作品尚未退回。

如果要搜索不区分大小写的字母字符串,可以使用 ILIKE 条款:

select name, house_no from people where name ilike '%r%';

       name     | house_no
  --------------+----------
   Roger Jones  |       33
   Sally Norman |       83
  (2 rows)

该查询每隔一次返回 people 对象,并使用 rR 以他们的名义。

15.4.3. 加入

如果您想要查看此人的详细信息和街道名称,而不是ID,该怎么办?为此,您需要在单个查询中将这两个表联接在一起。让我们来看一个例子:

select people.name, house_no, streets.name
from people,streets
where people.street_id=streets.id;

备注

使用连接,您将始终说明信息来自的两个表,在本例中为People和Streets。您还需要指定哪两个键必须匹配(外键和主键)。如果您不指定,您将得到一个列表,列出所有可能的人和街道组合,但无法知道谁真正住在哪条街道上!

下面是正确的输出:

     name     | house_no |    name
--------------+----------+-------------
 Joe Bloggs   |        3 | Low Street
 Roger Jones  |       33 | High street
 Sally Norman |       83 | High street
 Jane Smith   |       55 | Main Road
(4 rows)

我们将在稍后创建更复杂的查询时重新访问联接。只需记住,它们提供了一种简单的方法来组合来自两个或更多表的信息。

15.4.4. 子选择

子选择允许您基于通过外键关系链接的另一个表中的数据从一个表中选择对象。在我们的例子中,我们希望找到住在特定街道上的人。

首先,让我们对我们的数据进行一点调整:

insert into streets (name) values('QGIS Road');
insert into streets (name) values('OGR Corner');
insert into streets (name) values('Goodle Square');
update people set street_id = 2 where id=2;
update people set street_id = 3 where id=3;

让我们快速查看一下这些更改后的数据:我们可以重用上一节中的查询:

select people.name, house_no, streets.name
from people,streets
where people.street_id=streets.id;

结果:

     name     | house_no |    name
--------------+----------+-------------
 Roger Jones  |       33 | High street
 Sally Norman |       83 | High street
 Jane Smith   |       55 | Main Road
 Joe Bloggs   |        3 | Low Street
(4 rows)

现在,让我们向您展示对此数据的子选择。我们只想展示那些住在 street_id1

select people.name
from people, (
    select *
    from streets
    where id=1
  ) as streets_subset
where people.street_id = streets_subset.id;

结果:

     name
--------------
 Roger Jones
 Sally Norman
(2 rows)

虽然这是一个非常简单的示例,对于我们的小数据集来说是不必要的,但它说明了在查询大型和复杂的数据集时,子选择是多么有用和重要。

15.4.5. 聚合查询

数据库的强大功能之一是能够汇总其表中的数据。这些摘要称为聚合查询。下面是一个典型的例子,它告诉我们People表中有多少个People对象:

select count(*) from people;

结果:

 count
-------
     4
(1 row)

如果我们想要按街道名称汇总计数,我们可以这样做:

select count(name), street_id
from people
group by street_id;

结果:

 count | street_id
-------+-----------
     2 |         1
     1 |         3
     1 |         2
(3 rows)

备注

因为我们还没有使用 ORDER BY 子句中,结果的顺序可能与此处显示的顺序不匹配。

Try Yourself 适度

按街道名称汇总人员,并显示实际的街道名称,而不是Street_ID。

15.4.6. In Conclusion

您已经了解了如何使用查询返回数据库中的数据,使您能够从中提取有用的信息。

15.4.7. What's Next?

接下来,您将了解如何从您编写的查询创建视图。