SOQL的结构可以整理成下述的结构
SELECT fieldList [subquery][...]
[TYPEOF typeOfField whenExpression[...] elseExpression END][...]
FROM objectType[,...]
[USING SCOPE filterScope]
[WHERE conditionExpression]
[WITH [DATA CATEGORY] filteringExpression]
[GROUP BY {fieldGroupByList|ROLLUP (fieldSubtotalGroupByList)|CUBE
(fieldSubtotalGroupByList)}
[HAVING havingConditionExpression] ]
[ORDER BY fieldOrderByList {ASC|DESC} [NULLS {FIRST|LAST}] ]
[LIMIT numberOfRowsToReturn]
[OFFSET numberOfRowsToSkip]
[{FOR VIEW | FOR REFERENCE} ]
[UPDATE {TRACKING|VIEWSTAT} ]
[FOR UPDATE]
我们基于这个内容分开来看
语句 | 描述 | 备注 |
---|---|---|
fieldList subquery | 基于逗号分隔的一个或者多个字段,字段可以基于本表,这个表的父表数据,这个表的子表查询 | |
基于本表字段查询或者查询本表数量: | ||
SELECT Id, Name, BillingCity FROM Account | ||
SELECT count() FROM Contact | ||
查询关联父表数据: | ||
SELECT Contact.Firstname, Contact.Account.Name FROM Contact | ||
查询关联子表数据 | ||
SELECT Account.Name, (SELECT Contact.LastName FROM | ||
Account.Contacts) | ||
FROM Account | demo中的父表查询中,我们可以看到 Contact.Account.Name,原因是Contact上有一个 lookup字段关联到 Account,字段API Name为 AccountId,基于标准字段,把Id移除,然后搜索父表即可。 | |
引申,如果想要搜索 CreatedById的user的数据,可以搜索成 | ||
Contact.CreatedBy.UserName。 | ||
基于自定义的父表字段, API Name以后缀 __c结尾,搜索时使用 __r.字段名即可 | ||
typeOfField | 如果当前的字段可能是多个表类型情况下,可以通过 typeOfField来进行判断。这个更多的时候是应用于Event/Task表。Event/Task的WhatId可能是多个表,比如 Account / Contact/ CustomObject等,可以基于 TypeOfField来进行判断来做不同的定制化处理。 | |
下面例子为:搜索Event字段,如果当前的 WhatId是 Account情况下,搜索 Phone字段,否则搜索Name字段 | ||
SELECT | ||
TYPEOF What | ||
WHEN Account THEN Phone | ||
ELSE Name | ||
END | ||
FROM Event | ||
WHERE CreatedById IN | ||
( | ||
SELECT CreatedById | ||
FROM Case | ||
) | typeof只能用于46及以上的api版本。 | |
语法为: | ||
TYPEOF typeOfField | ||
WHEN whenObjectType THEN whenFieldList} | ||
ELSE elseFieldList | ||
END] | ||
ELSE为可选项 | ||
不是所有的情况都支持 typeof,使用typeof关键字以前,先查询一下文档,了解限制 | ||
FROM object | 指定查询表的API Name,比如 Account,Contact,自定义表等 | |
USING SCOPE | 基于指定范围返回结果集,比如返回只有自己own的数据或者在当前用户territory的数据等。 | |
filterScope | filterScope搭配 USING SCOPE一起使用,filterScope有以下的可选值。 参考下面的表格信息 | |
WHERE | 包括一个或者多个的条件表达式用于过滤数据 | |
conditionExpression | 如果指定了WHERE,通过字段以及值进行数据过滤。 | |
比如获取名字为 Zhang San的Account数据 | ||
SELECT Id, Name FROM Account Where Name = 'Zhang San’ | ||
WITH | 基于字段值进行数据过滤。和WHERE的过滤数据不同,with基于以下几种情况使用: | |
WITH DATA CATEGORY:搜索Knowledge Article表,基于knowledge category | ||
WITH SECURITY_ENFORCED:在apex class中基于当前用户访问权限的表和字段进行查询,基于FLS以及object permission | WITH SECURITY_ENFORCED建议使用API 45版本以上。 | |
默认apex中使用 system mode,会忽略当前的表和字段的访问权限。即使没有表和字段的访问权限,也可以基于数据权限访问,如果使用 WITH SECURITY_ENFORCED,则会基于当前权限访问。比如 | ||
SELECT Id,XX__c from CustomObject__c | ||
WITH SECURITY_ENFORCED | ||
如果当前用户没XX__c访问权限,则会报错,并且不返回任何内容。 | ||
WITH SECURITY_ENFORCED也有很多限制,使用以前查询相关限制 | ||
GROUP BY | 基于组返回数据而不是返回每条独立的数据,GROUP BY可以和聚合函数一起使用,比如 SUM()或者MAX()。聚合函数参考下面的表格内容 | |
GROUP BY ROLLUP | 返回聚合数据的子汇总(subtotal),可以最多返回三个字段的子total的汇总内容。同上一个步骤的举个函数内容。同一个语句中不能一起使用GROUP BY 以及GROUP。 | |
举例: | ||
SELECT Status, LeadSource, COUNT(Name) cnt | ||
FROM Lead | ||
GROUP BY ROLLUP(Status, LeadSource) | ||
GROUP BY CUBE | 为查询结果中分组字段的所有组合做子汇总。这个动作对于编制跨表格的数据报告很有用。带有GROUP BY CUBE子句的查询与带有GROUP BY子句的同等查询返回相同的聚合数据。它还会为在逗号分隔的分组列表中指定的每个字段组合返回额外的小计行,以及一个总计数。 | |
可以在一个GROUP BY CUBE子句中包含最多三个字段 | ||
fieldGroupByList | 用于汇总数据,多个字段,通过逗号分隔 | |
fieldSubtotalGroupByList | 最多三个字段,用于进行子结果集汇总,通过逗号分隔 | |
Having | 和group一起使用,通过聚合函数情况下,对结果集进行过滤。 | |
举例:返回内容为基于 lead source汇总,并且要求数量超过100个。 | ||
SELECT LeadSource, COUNT(Name) | ||
FROM Lead | ||
GROUP BY LeadSource | ||
HAVING COUNT(Name) > 100 | ||
havingConditionExpression | having情况下的条件表达式 | |
ORDER BY | 基于一个或者多个字段进行排序。可以设置字段正序或者倒序。{ASC | DESC} |
如果记录有null的情况,可以设置NULLS {FIRST | LAST} 来确定NULL的记录是前面展示还是后面展示 | |
LIMIT | 限制返回数据的数量 | 非batch同步情况下,最多一个transaction只能搜索50000条 |
OFFSET | 偏移量,用于分页用,比如可以使用OFFSET获取数据为 51条到75条数据。此种情况为LIMIT 25 OFFSET 50 | OFFSET最多只支持2000 |
FOR VIEW | 当使用FOR VIEW语句,会发生两个情况。 | |
LastViewedDate字段将会被更新 | ||
RecentlyViewed表将会自动生成一条数据用来反映到最新查看到的数据 | ||
FOR REFERENCE | 用于在自定义接口(自定义页面或者手机页面等)情况下,通知salesforce什么时间这条记录被引用。当使用 FOR REFERENCE语句,会发生两个情况。 | |
LastReferencedDate字段将会被更新 | ||
RecentlyViewed表将会自动生成一条数据 | ||
UPDATE | 用于knowledge表中,详见文档 | |
FOR UPDATE | 在apex情况下,使用 FOR UPDATE用于在数据被更新情况下锁object数据,用于避免数据竞争条件以及其他的线程安全问题 |
filterScope可选内容如下:
delegated | 基于delegated user进行过滤 |
---|---|
everything | 基于所有的数据过滤 |
mine | 基于当前数据owner过滤 |
mine_and_my_groups | 基于当前user以及user queue过滤数据。这个只适用于ProcessInstanceWorkItem表 |
my_territory | 基于当前user territory过滤数据。这个只适用于 territory management在组织启用情况下 |
my_team_territory | 基于当前 user team territory过滤数据。这个只适用于 territory management在组织启用情况下 |
scopingRule | 基于可用的 scoping rule来过滤数据。只适用于当前查询的object启用了至少一个 |
scoping rule | |
team | 基于分配的team进行过滤,比如account team |
聚合函数有以下内容:
| AVG() | 返回数字类型的平均值,比如 SELECT CampaignId, AVG(Amount) FROM Opportunity GROUP BY CampaignId | | --- | --- | | COUNT() and COUNT(fieldName) | 返回满足情况的数据的数量。比如 SELECT COUNT() FROM Account WHERE Name LIKE 'a%' COUNT以及COUNT(fieldName)都是返回基于条件的数据量,COUNT(fieldName)要求字段值非空,通常和group by一起使用 | | COUNT_DISTINCT() | 返回满足条件的去重非空的数据的数量。比如: SELECT COUNT_DISTINCT(Company) FROM Lead | | MIN() | 返回字段的最小值。比如 SELECT MIN(CreatedDate), FirstName, LastName FROM Contact GROUP BY FirstName, LastName | | MAX() | 返回字段最大值。比如 SELECT Name, MAX(BudgetedCost) FROM Campaign GROUP BY Name | | SUM() | 返回数值类型的总计值。比如: SELECT SUM(Amount) FROM Opportunity WHERE IsClosed = false AND Probability > 60 |