运用绑定变量和聚合函数
学习目标
完成本单元后,您将能够:
- 通过插入 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
的值在查询外部设定。我们看一下它的实际操作。
- 在您的 Trailhead Playground 中单击 ,在搜索框中输入
Dream
,然后选择 DreamHouse 应用程序。
- 单击 Property Explorer。
Property Explorer 根据一些筛选条件,例如最高价格范围,搜索在售的房产。最高价格滑块接受 maxHomeValue 绑定变量的值。
- 将最高价格滑块移动到 550K。
每次移动滑块时,通过它的绑定变量修改代码中它的关联值。运行查询,并把结果添加到 Property Explorer 页面显示的房产列表中。
在 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 处房产中每一处的所在城市。
因为我们不想要整个城市列表,所以修改查询,使用一个聚合函数。要想得到房产总数,使用 COUNT() 函数。
聚合函数出现在查询的 SELECT 子句中,如下所示:
函数名称后面的括号包含计算中用到的字段名称。在这个例子中,我们要数 City__c 字段中的值。
运行 COUNT() 查询
- 在查询编辑器中,输入:
SELECT City__c FROM Property__c
- 单击执行。
您的查询结果应该有 12 行,每处房产的所在城市。
- 编辑这条查询,把 City__c 字段插入到 COUNT() 函数中,如下所示:
SELECT COUNT(City__c) FROM Property__c
- 单击执行。
您的查询结果应该是 12,根据 City__c 字段得到的房产数量。
如果您注意到了所有 12 处房产只分布在 2 个城市,您可能会疑惑为什么计数是 12 而不是 2。这是因为 COUNT() 函数把所有值算在内,往往包含具有相同值的多条记录。
假设我们想把一位经纪人分配给一座城市中的所有房产。我们需要多少位经纪人?换句话说,12 处房产代表多少个唯一的城市?为了只计算唯一的城市,我们需要另一个函数。(听到“唯一”的时候,您就会想到“不同”。)
COUNT_DISTINCT() 与 COUNT() 很相似,只不过它只返回唯一的值(去重)。
运行 COUNT_DISTINCT 查询
- 在查询编辑器中,编辑查询,使用 COUNT_DISTINCT() 函数,如下所示:
SELECT COUNT_DISTINCT(City__c) FROM Property__c
- 单击执行。
现在您的结果应该是 2,所有房产中唯一 City__c 值的数量。
Cambridge、Boston 和 Brookline 是在 City__c 字段中找到的几个唯一值。请注意 COUNT() 和 COUNT_DISTINCT() 函数是区分大小写的。那表示 Cambridge 与 cambridge 不算重复。Cambridge 和 cambridge 被视作两个唯一的值。
MIN()、MAX()、AVG() 和 SUM()
其他有用的聚合函数包括 MIN()、MAX()、AVG() 和 SUM()。
MIN() 和 MAX() 函数的用处一目了然。MIN() 找到最小(最低)的值,而 MAX() 找到最大(最高)的值。但是这些函数有一些特别之处。它们可以处理日期和时间以及数字。
- 在查询编辑器中,输入:
SELECT MIN(Date_Listed__c) FROM Property__c
- 单击执行。
MIN() 函数返回最早的日期。MAX() 函数返回最晚(最近)的日期。
MIN() 和 MAX() 函数也可以识别选项列表值的排序方式,所以您可以找到某个选项列表中的第一个或最后一个值。
AVG() 函数计算所有值的平均值。SUM() 函数计算所有值的总和。因为这两个函数都要执行计算,因此它们只适用于包含数字值的字段。
将聚合函数的结果进行分组
根据聚合数据计算值后,您可能想分组报告结果,跟摘要式报表中那样。要想把 SOQL 查询中的值进行分组,使用 GROUP BY 子句。比如,DreamHouse Realty 的一个客户想知道哪些经纪人卖出(成交)了某处房产。
练习 GROUP BY 子句
下一步,在查询中使用 GROUP BY 子句。
- 在查询编辑器中,输入:
SELECT MAX(Status__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name
- 单击执行。
您的结果应该有八行。
记住,该查询按经纪人对房产进行分组。对于每个经纪人的房产,我们列出 Status__c 的最新值。那是与最终的选项列表值最接近的“状态”选项列表值。我们想要卖出了房产的经纪人,因此我们要进一步缩小结果范围。回到画图板。
筛选聚合函数的结果
另一种缩小结果范围的方法是使用 HAVING 子句。HAVING 子句筛选聚合函数返回的结果。
嗯……这听起来有点像我们可以用来查找卖出房产的经纪人的东西。我们之前的查询返回包含任何状态的房产的经纪人列表。可以尝试使用 HAVING 子句来缩小那些结果的范围。
- 在查询编辑器中,输入:
SELECT MAX(Status__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name HAVING MAX(Status__c) = 'Closed'
- 单击查询。您会得到一个经纪人。
耶!对了。使用 HAVING 子句把结果范围缩小到状态是“已关闭”的房产。做得好!
WHERE 子句与 HAVING 子句很像,对吧?下面介绍如何确定什么时候使用 WHERE,什么时候使用 HAVING。
- WHERE 子句筛选没有聚合函数的 SOQL 查询中的记录。
- HAVING 子句在数据用聚合函数聚合后筛选结果。
您在本模块中学过,SOQL 是一个访问 Salesforce 组织中的数据的好工具。随着您继续掌握并拓展您的 Apex 编码技能,您会遇到许多运用您的 SOQL 知识的机会。运用您的知识的时候,记住您可以在本模块提供的资源中找到关于 Apex 和 SOQL 的详细说明、例子以及更多信息。现在,去试试用 SOQL 查询吧。
资源
-
Salesforce 开发人员文档:在 SOQL 和 SOSL 查询中使用 Apex 变量
-
Salesforce 开发人员文档:聚合函数
-
Salesforce 开发人员文档:SELECT 子句示例
-
Salesforce 开发人员文档:分组依据