Skip to main content
Build the future with Agentforce at TDX in San Francisco or on Salesforce+ on March 5–6. Register now.

运用绑定变量和聚合函数

学习目标

完成本单元后,您将能够:

  • 通过插入 Apex 绑定变量使查询变成动态的。
  • 使用聚合函数累计和汇总查询中的数据。
  • 对查询结果应用分组。
  • 能够辨别什么时候使用 WHERE 子句,什么时候使用 HAVING 子句。

跟随 Trail Together 进行学习

进行这一步骤时,想要跟随专家一起学习吗?查看此视频,它是 Trailhead Live 上 Trail Together 系列的一部分。

(此视频片段从 1:10:42 开始,如果您想要倒回去再次观看步骤的开头部分可以从这里开始。)

简介

我们讨论了如何编写基本的 SOQL 查询,以及如何构思包含父或子对象中的字段的查询。不过,您也知道,每个应用开发项目都是独一无二的。知道如何自定义业务逻辑以解决具体问题很重要。

绑定变量

使用绑定变量是定制代码的一种方式。它类似于在用户界面中打开一个表单,修改某个输入字段,搜索特定结果。下面我们来看一个 DreamHouse 应用程序的例子。您是一位卖房子的房地产经纪人,您想查看总价在 20 万美元以下的房子的库存。于是您写了这条查询:

List<Property__c> property = [SELECT Id, Name, Price__c FROM Property__c WHERE Price__c < 200000];

对您来说很简单,但它是静态的。该查询总是返回总价在 20 万美元以下的房子。那其他不会编写 SOQL 查询并在 Developer Console 中运行查询的经纪人和潜在买家怎么办呢?他们需要更简单的方法按适合他们的价格筛选房子。您如何为一位预算在 20 万美元的买家和另一位预算是 80 万美元的买家编写一条查询?这时可以用绑定变量。绑定变量是一种可以用在 SOQL 查询中的 Apex 变量。把绑定变量用作之后提供的特定值的占位符。

备注

这并不是什么新鲜概念。在管理员面向对象的编程中,您学过使用参数作为方法中的占位符。当您调用该方法时,您传递一个替换那个参数的参数。查询中的绑定变量就像方法中的参数。运行查询时,绑定变量被特定值取代。

假设有一个名叫 maxHomeValue 的绑定变量。我们在 Apex 中声明这个变量,然后在查询中使用这个变量,如下所示:

Integer maxHomeValue = 200000;
List<Property__c> property = [SELECT Name, Price__c FROM Property__c WHERE Price__c < :maxHomeValue];

请注意在查询中,绑定变量的前面有一个冒号 (:)。该查询返回房产对象的名称和价格。但是按房子的价格筛选了结果:WHERE Price__c < :maxHomeValue。绑定变量 maxHomeValue 的值在查询外部设定。我们看一下它的实际操作。

  1. 在您的 Trailhead Playground 中单击 应用程序启动器,在搜索框中输入 Dream,然后选择 DreamHouse 应用程序。
  2. 单击 Property Explorer
    Property Explorer 根据一些筛选条件,例如最高价格范围,搜索在售的房产。最高价格滑块接受 maxHomeValue 绑定变量的值。
  3. 将最高价格滑块移动到 550K

每次移动滑块时,通过它的绑定变量修改代码中它的关联值。运行查询,并把结果添加到 Property Explorer 页面显示的房产列表中。

滑块设定 Apex 代码中的变量值。那些值取代查询中的变量占位符。

WHERE 子句中使用绑定变量,您可以在运行查询前,设定代码中的变量值。绑定变量使查询变成动态的。要想为每个用户定制查询,可以根据用户输入设定绑定变量的值。随着您继续修改和复查代码,您会发现有许多数据不断变化的字段类型。

聚合函数

在报表中,您使用累计汇总字段来计算来自相关记录的值。比如,您可能想计算房产总数,或某个城市的房产的均价或最高价。在 SOQL 中,您用聚合函数来执行那些以及其他一些计算。

用于 SOQL 查询的聚合函数

聚合函数

描述

示例

COUNT()

返回与该字段关联的行数

SELECT COUNT(Name)FROM Broker__c

COUNT_DISTINCT()

返回符合查询条件的唯一行数

SELECT COUNT_DISTINCT(City__c)FROM Property__c

MIN()

返回字段的最小值

SELECT MIN(Days_On_Market__c)FROM Property__c

MAX()

返回字段的最大值

SELECT MAX(Beds__c)FROM Property__c

AVG()

返回数字字段的平均值

SELECT City__c, AVG(Days_On_Market__c)FROM Property__c GROUP BY City__c

SUM()

返回数字字段的总值

SELECT SUM(Price__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name

我们以某个城市的房产为例。假设我们从这条简单的查询开始:

SELECT City__c FROM Property__c

该查询返回 12 处房产中每一处的所在城市。

查询结果——总行数:12。表格有一列,显示城市。

因为我们不想要整个城市列表,所以修改查询,使用一个聚合函数。要想得到房产总数,使用 COUNT() 函数。

聚合函数出现在查询的 SELECT 子句中,如下所示:

SELECT COUNT(City__c) FROM Property__c.COUNT 是聚合函数,City__c 是字段,而 Property__c 是对象。

函数名称后面的括号包含计算中用到的字段名称。在这个例子中,我们要数 City__c 字段中的值。

运行 COUNT() 查询

  1. 在查询编辑器中,输入:
    SELECT City__c FROM Property__c
  2. 单击执行
    您的查询结果应该有 12 行,每处房产的所在城市。
  3. 编辑这条查询,把 City__c 字段插入到 COUNT() 函数中,如下所示:
    SELECT
    COUNT(City__c)
     FROM Property__c
  4. 单击执行
    您的查询结果应该是 12,根据 City__c 字段得到的房产数量。
    查询结果——总行数:1。表格显示一个值:12。

如果您注意到了所有 12 处房产只分布在 2 个城市,您可能会疑惑为什么计数是 12 而不是 2。这是因为 COUNT() 函数把所有值算在内,往往包含具有相同值的多条记录。

假设我们想把一位经纪人分配给一座城市中的所有房产。我们需要多少位经纪人?换句话说,12 处房产代表多少个唯一的城市?为了只计算唯一的城市,我们需要另一个函数。(听到“唯一”的时候,您就会想到“不同”。)

COUNT_DISTINCT() 与 COUNT() 很相似,只不过它只返回唯一的值(去重)。

运行 COUNT_DISTINCT 查询

  1. 在查询编辑器中,编辑查询,使用 COUNT_DISTINCT() 函数,如下所示:
    SELECT COUNT_DISTINCT(City__c) FROM Property__c
  2. 单击执行
    现在您的结果应该是 2,所有房产中唯一 City__c 值的数量。
    查询结果——总行数:1。列:count_distinct(City__c) 值是 2。

Cambridge、Boston 和 Brookline 是在 City__c 字段中找到的几个唯一值。请注意 COUNT() 和 COUNT_DISTINCT() 函数是区分大小写的。那表示 Cambridge 与 cambridge 不算重复。Cambridge 和 cambridge 被视作两个唯一的值。

MIN()、MAX()、AVG() 和 SUM()

其他有用的聚合函数包括 MIN()、MAX()、AVG() 和 SUM()。

MIN() 和 MAX() 函数的用处一目了然。MIN() 找到最小(最低)的值,而 MAX() 找到最大(最高)的值。但是这些函数有一些特别之处。它们可以处理日期和时间以及数字。

  1. 在查询编辑器中,输入:
    SELECT MIN(Date_Listed__c) FROM Property__c
  2. 单击执行

MIN() 函数返回最早的日期。MAX() 函数返回最晚(最近)的日期。

MIN() 和 MAX() 函数也可以识别选项列表值的排序方式,所以您可以找到某个选项列表中的第一个或最后一个值。

AVG() 函数计算所有值的平均值。SUM() 函数计算所有值的总和。因为这两个函数都要执行计算,因此它们只适用于包含数字值的字段。

将聚合函数的结果进行分组

根据聚合数据计算值后,您可能想分组报告结果,跟摘要式报表中那样。要想把 SOQL 查询中的值进行分组,使用 GROUP BY 子句。比如,DreamHouse Realty 的一个客户想知道哪些经纪人卖出(成交)了某处房产。

练习 GROUP BY 子句

下一步,在查询中使用 GROUP BY 子句。

  1. 在查询编辑器中,输入:
    SELECT MAX(Status__c), Broker__r.Name
    FROM Property__c
    GROUP BY Broker__r.Name
  2. 单击执行
    您的结果应该有八行。
    查询结果——总行数:8,列 1——max(Status__c),列 2——Name。

记住,该查询按经纪人对房产进行分组。对于每个经纪人的房产,我们列出 Status__c 的最新值。那是与最终的选项列表值最接近的“状态”选项列表值。我们想要卖出了房产的经纪人,因此我们要进一步缩小结果范围。回到画图板。

筛选聚合函数的结果

另一种缩小结果范围的方法是使用 HAVING 子句。HAVING 子句筛选聚合函数返回的结果。

嗯……这听起来有点像我们可以用来查找卖出房产的经纪人的东西。我们之前的查询返回包含任何状态的房产的经纪人列表。可以尝试使用 HAVING 子句来缩小那些结果的范围。

  1. 在查询编辑器中,输入:
    SELECT MAX(Status__c), Broker__r.Name
    FROM Property__c
    GROUP BY Broker__r.Name
    HAVING MAX(Status__c) = 'Closed'
  2. 单击查询。您会得到一个经纪人。
    查询结果——总行数:1。列 1:max(Status__c)。列 2:Name。

耶!对了。使用 HAVING 子句把结果范围缩小到状态是“已关闭”的房产。做得好!

WHERE 子句与 HAVING 子句很像,对吧?下面介绍如何确定什么时候使用 WHERE,什么时候使用 HAVING。

  • WHERE 子句筛选没有聚合函数的 SOQL 查询中的记录。
  • HAVING 子句在数据用聚合函数聚合后筛选结果。

您在本模块中学过,SOQL 是一个访问 Salesforce 组织中的数据的好工具。随着您继续掌握并拓展您的 Apex 编码技能,您会遇到许多运用您的 SOQL 知识的机会。运用您的知识的时候,记住您可以在本模块提供的资源中找到关于 Apex 和 SOQL 的详细说明、例子以及更多信息。现在,去试试用 SOQL 查询吧。

资源

在 Salesforce 帮助中分享 Trailhead 反馈

我们很想听听您使用 Trailhead 的经验——您现在可以随时从 Salesforce 帮助网站访问新的反馈表单。

了解更多 继续分享反馈