计算字段值

字段计算允许托管要素图层所有者或组织管理员更改图层属性表中单个字段每一行的值。

例如,如果您具有一个用于存储房产销售相关信息的托管要素图层 - 其中包括房产所在地的销售价格及税率 - 则您可以向该图层添加一个字段用来存储估计的房产税。 要填充 estimated_property_taxes 字段,请为该字段定义一个计算表达式,该表达式取用 sale_price 字段中的值并将其与 tax_rate 值相乘。

在托管要素图层图层中的字段内编写计算表达式时,有两个选项可供使用:

  • ArcGIS Arcade - 如果计算需要的功能比 SQL 更多,则 Arcade 是理想之选,因为 Arcade 可以提供对属性值和要素集合的访问权限,从而允许您创建包含空间运算的表达式。 此外,如果在计算特定行时发生错误,您可以停止计算并解决问题,并在更正问题后再次开始计算。

    注:

    将不会使用最新 ArcGIS Arcade 语言功能更新 ArcGIS API for JavaScript 3.44 及更高版本。 在 3.44 或更高版本 JavaScript API 应用程序中编写的 Arcade 表达式将仅支持在 Arcade 1.21 或更低版本中引入的 Arcade 语言功能。 有关 ArcGIS 产品中 Arcade 语言支持的详细信息,请参阅 Arcade 版本矩阵

  • SQL - 使用 SQL 以最高的性能进行计算,可以使用非空间属性上的标准化 SQL (SQL-92) 表达式执行这些计算。 您可以在启用同步的托管要素图层和为追踪要素创建者和编辑者配置的图层上运行 SQL;但是无法对这些图层运行 Arcade 表达式。

以下部分将介绍如何在托管要素图层的项目页面中计算字段的值。 后续部分将提供常见计算的示例。

从项目页面计算字段值

请按照这些步骤从要素图层的项目页面计算字段中的字符串、数字或日期字段值。

注:

无法撤消字段计算。 因此,建议您添加一个字段,并在字段中计算值,然后确认计算是否为您想要的结果。 如果是,则可对原始字段进行同所添加字段相同的计算。 确认原始字段中的计算值完全正确后,您可以删除所添加的字段。

  1. 在图层的项目页面中,单击数据选项卡以显示表。
  2. 单击包含要计算的值的列。
  3. 执行以下操作之一打开计算字段对话框:
    • 单击计算
    • 单击显示详细视图 > 计算
  4. 选择用于计算的语言,ArcadeSQL

    如果托管要素图层已启用同步或已被配置为追踪要素创建者和更新者,则不会显示此页面, 而将显示 SQL 窗口。

  5. 组建计算表达式。
    • 对于 SQL,请使用基本运算符、字段列表和函数。 单击验证按钮,以确保表达式中没有错误。 若表达式无效,则可单击移除按钮并组建一个新的表达式。 表达式完整有效时,单击计算
    • 对于 Arcade,使用全局变量、函数和常量。 单击确定以运行表达式。 如果运行表达式时发生错误,可以单击查看错误打开表达式窗口以修复错误。 否则,单击取消。 更正表达式并再次运行后,计算将重新开始。

完成计算所需的时间取决于表达式的复杂程度以及图层中的要素数。

示例计算

以下部分提供了在 ArcGIS Online 中执行常见计算的示例语法。

对两个现有字段中的数值执行数学运算以填充第三个字段

可以执行的最常见计算之一是根据要素图层中的现有值来得到新数值。 例如,可以将所有商店某一年的销售总额减去另一年的销售总额,以了解从某一年到下一年的利润变化,或者可以将 18 岁以下的居民总数除以总人口数,以确定 18 岁以下人口的比重。

Arcade 示例

计算两个数值字段 Sales2016 和 Sales2017 的值的差值,以填充数值字段。

$feature.Sales2016 - $feature.Sales2017

SQL 示例

使用小数来填充数值字段,该小数是计算 18 岁以下人口比重的结果。

PopUnder18/TotalPop

将现有字段中的字符串值连接到新的字符串字段中

用于填充新字段的另一个计算涉及对现有字符串字段中的值进行组合。 例如,对于酒店中的房间位置,您可能拥有两个字符串字段 Floor 和 Room,并且您希望将其组合到一个同时包含两者的字符串字段中。

在以下示例中,会将 Floor 和 Room 字段的值组合到单个字段中。

Arcade 示例

Concatenate($feature.room,$feature.floor)

SQL 示例

CONCAT(Floor,Room)

从字符串字段中移除尾随空格或前导空格

当用户在编辑时在字段中输入或粘贴值时,可能会出错,在文本中留下尾随空格或前导空格。 可以通过对值进行修剪来清除这些错误。

在这些示例中,假设您已知编辑者在将 New Hampshire 粘贴到用于存储州名称的字段中时添加了尾随空格,因此您需要从字符串末尾修剪此空格。

Arcade 示例

Trim('New Hampshire ')

SQL 示例

Trim(TRAILING ' ' FROM 'New Hampshire ')

使用不同的值来填充字段,这些值取决于另一字段中的值

有时,您希望添加至字段的值会根据要素以及相同要素的其他值而发生变化。 例如,可以将一个字符串字段添加到要素图层,以存储用于描述另一个字段中的数值或缩写字符串值的文本。 由于 SQL 计算接口不支持此功能,因此对于这些类型的计算,请使用 Arcade

Arcade 示例

以下示例根据图层中另一字段中的数字 (HowMany),在不同条件下将不同的字符串值(None、Low、High 或 Other)写入文本字段。

When(
  $feature.HowMany == 0, "None",
  $feature.HowMany == 1, "Low",
  $feature.HowMany == 2,  "High",
"Other")

将一个值替换为另一个值

如果需要将现有值替换为另一个值(例如,您表示某个特定值的方式已更改,或者您需要更正输错的值),则可以查找字段的所有现有值,然后将其替换为新值。 由于 SQL 计算接口不支持此功能,因此对于这些类型的计算,请使用 Arcade

警告:

计算将立即保存到要素图层。 如果您错误地覆盖了现有值,则将需要重新计算以将值更改回来。

Arcade 示例

本示例将使用 Replace 函数将英式拼写(彩色)更改为美式拼写。

Replace($feature.color, 'colour', 'color')

确定每个要素面积的数值属性的密度

要计算某区域内一个属性的密度,请使用 Arcade 表达式,原因在于您无法在计算接口中对空间字段执行 SQL 计算。

Arcade 示例

本示例通过将总人口值 (TotalPop) 除以面要素的面积(以平方英里为单位)来确定每个要素的人口密度:

$feature.TotalPop / Area ($feature,
'square-miles')

获取点要素的坐标

可以使用 Arcade 表达式,以在仅包含点的托管要素图层中返回空间字段的经度和纬度。

计算接口不支持对空间字段进行此类型的计算。

Arcade 示例

本示例使用 Geometry 函数来计算点图层中每个点的 x 坐标字段。

Geometry($feature).x

增加或减去日期中的时间

您可能需要增加或减去日期字段或日期文本值中的时间,以生成更新的日期字段。 例如,可通过向日期中添加时间来计算日后检查或验证的日期。

Arcade 示例

本示例使用 DateAdd 函数将日期增加七天,以获得以下周的日期。

var startDate = Date($feature.dateField);
var oneWeekLater = DateAdd(startDate, 7, 'days');
return oneWeekLater;

SQL 示例

可通过以下计算来增加或减去日期字段中的时间,也可使用支持 SQL 的日期文本值。 第一种使用日期字段进行计算,第二种使用日期文本值进行计算。 也可以使用数字字段和数字文本。 支持字段和文本的任意组合,如第三种和第四种计算所示。

<DateField> +/- <NumberField> = updated date
DATE'<SQL-supported Date Literal>'  +/- <Number of Days> = updated date
<DateField> +/- <Number of Days> = updated date
DATE'<SQL-supported Date Literal >'  +/- <NumberField> = updated date

计算出的日期字段为原始日期加上或减去您希望增加或减少的天数。 天数既可以是整数也可以包含小数 - 例如,1.5 表示一天半或 36 小时。

在以下示例中,该机器安装于 6/14/2016 的 10:00 a.m。您可以使用以下任意一种计算来生成此安装日期一个月(30 天)后的检查日期。 第一种计算使用值为 6/14/2016 的日期字段和值为 30 的数字字段,而第二种计算使用的是日期文本和数字文本。

<MyDateField> + <MyNumberField> = 7/14/2016 10:00 AM
DATE'6/14/2016' + 30 = 7/14/2016 10:00 AM

计算两个日期之间的差值

您可能希望计算两个日期间的时间长度。 例如,如果您同时掌握了电表的安装日期和检查日期,则您可以计算两个日期之间的差值,以验证安装和检查之间的时间长度是否符合允许的标准。 计算结果为数字字段而非日期字段。

Arcade 示例

以下示例使用 DateDiff 函数,以通过求出当前日期 (endDate) 与某人的出生日期 (startDate) 的差值来计算其年龄:

var startDate = Date($feature.startDateField);
var endDate = Date($feature.endDateField);
var age = DateDiff(endDate, startDate, 'years');
return age;

SQL 示例

可使用任意日期字段和日期文本的组合来计算两个日期间的时间长度。 下面的第一种计算使用日期字段,而第二种计算使用日期文本。 第三种和第四种计算同时使用日期字段和日期文本。

<DateField1> - <DateField2> = number of days in between
DATE'<SQL-supported Date Literal>' - DATE'< SQL-supported Date Literal>' = number of days in between
<DateField1> - DATE'<SQL-supported Date Literal>' = number of days in between
DATE'<SQL-supported Date Literal>' - <DateField2>  = number of days in between

其结果为从一个日期字段或文本中减去另一个日期字段或文本计算得出的数字字段。 该数字结果(以天为单位)既可以是整数也可以包含小数 - 例如,1.5 表示一天半或 36 小时。

在上文中的电表检查示例中,可使用以下任一种计算来计算安装日期 6/1/2015 与检查日期 10/1/2015 之间的时间长度。 第一种计算使用日期字段,第二种计算使用日期文本,第三种和第四种计算同时使用日期字段和日期文本。

<InspectionDateField> - <InstallationDateField> = 122 (days)
DATE'10/1/2015' - DATE'6/1/2015' = 122 (days)
<InspectionDateField> - DATE'6/1/2015' = 122 (days)
DATE'10/1/2015' - <InstallationDateField> = 122 (days)

计算字段值时的注意事项

  • 当在 Map Viewer 经典版 中计算图层的值并且该图层中存在过滤器时,将仅计算符合过滤器条件的记录的值。
  • 在编写 SQL 表达式时,计算字段仅适用于字段名称,而不适用于字段别名。 字段列表可显示所有可进行计算的字段名称。 您可以按字符串数值日期等字段类型来过滤列表。
    • 如果将鼠标悬停在字段列表中的某个字段名称上,将显示字段别名和字段类型。
    • 如果单击字段列表中的字段名称,该字段将添加到表达式。
  • 您无法计算托管要素图层副本或具有相关切片图层的托管要素图层中的字段值。
  • 已计算的值不会从托管要素图层或视图传播至依赖托管场景图层。
  • SQL 表达式中的数值不支持区域设置特定格式。 例如,当将区域设置设置为西班牙时,您必须对属性表值使用小数点分隔符,而非逗号分隔符。
  • 您不能对双精度字段使用数值 MOD 函数。 如示例中所示,将字段转换成整数。
  • 您无法为已启用同步或已对配置跟踪要素创建者和上次更新人员配置的托管要素图层编写 Arcade 表达式。
  • 无法使用 Arcade 来计算要素图层项目页面中以下字段数据类型的值:
    • 大整数
    • 仅日期
    • 仅时间
    • 时间戳偏移

    注:

    当托管要素图层中的任何图层包含这些数据类型时,将禁用整个托管要素图层(甚至不包含不受支持的数据类型的子图层)的 Arcade 计算。

标准化 SQL (SQL-92) 参考

在编写 SQL 表达式以计算字段值时,使用标准化 SQL。 本部分提供了适用于 ArcGIS Online 中 SQL 计算的运算符和 SQL 函数的列表。

创建 SQL 表达式后,单击计算按钮。 如果出现任何错误,则对话框底部将显示一条错误消息。 更正表达式语法,然后重新计算。

运算符

计算字段对话框中,可使用加减乘除等运算符来构建简单 SQL 表达式。 使用这些运算符的示例和提示如下:

  • 要将 SAMPLE 数值字段中的所有值都乘以 100.0,请输入 SAMPLE * 100.0 作为表达式。
  • 对于更为复杂的公式,可使用圆括号来指定计算顺序,例如,SAMPLE * (BASELINE - 40)
  • 数学运算符不适用于字符串字段。 您将需要使用字符串函数部分中介绍的字符串函数。
  • 如果您要将双精度型的字段换算成整型的字段,则可能会自动将 CAST 函数添加到表达式中。 例如,如果您正在将名为 POP 的双精度字段换算成名为 SAMPLE 的整数字段,表达式将显示为 CAST(SAMPLE AS FLOAT)。 不要移除 CAST 函数。 有关 CAST 函数的信息,请参阅以下数值函数
  • 想要在字符串中包括单引号,需使用一对单引号。 例如 'Nightingale''s'。 不要使用双引号。

函数

除了使用运算符的简单表达式以外,您也可以使用函数来组建 SQL 表达式。 函数适用于字段名称、文本和其他函数。 例如,假设您需要将一个双精度字段的值换算成 TOTALPOP 除以 POP18。 如果任意要素的 POP18 等于零,计算将引发一个除数为零的错误。 您可以使用 NULLIF 函数来避免发生此类错误,如下所示。 表达式为 TOTALPOP / NULLIF(POP18, 0)

函数接受参数。 在下表中,任一参数都可为以下内容:

  • 字段名称,只要字段类型与参数类型(字符串、数值或日期)相匹配即可。
  • 文本,如 'Sailboat'(用单引号引起来的字符串),用单引号引起来的数字 5、MM/DD/YYYY hh:mm:ss 或 YYYY-MM-DD 格式的日期,或者 HH:MM:SS 格式的时间。
  • 可返回相应类型值(字符串、数值或日期)的函数。 例如,FLOOR(POWER(SAMP_ERR, 0.5)) 会返回小于或等于 SAMP_ERR 的平方根的最大整数。

出于举例说明的目的,下表描述列中的示例大多使用文本参数。 您可以用字段名称或其他函数来代替这些参数。

日期函数

可根据日期字段进行一系列计算。 例如,您可以增加或减去日期字段中的时间,或计算两个日期字段间的差值。

在使用日期字段之前,请阅读以下重要的注意事项

计算日期字段时可以使用任意日期和数字字段以及文本的组合。 使用日期文本时,必须使用支持 SQL 的日期格式。

可用的日期函数如下:

函数描述

CURRENT_DATE()

以 UTC 时间返回当前日期。

显示的值取决于您正在使用的客户端。 在 ArcGIS Online 中,将以您的组织或配置文件的时区来显示日期。

CURRENT_TIME()

返回当前 UTC 日期和时间(小时、分钟、秒)。

显示的值取决于您正在使用的客户端。 在 ArcGIS Online 中,将以您的组织或配置文件的本地时间来显示时间。

CURRENT_TIMESTAMP()

返回当前 UTC 日期和时间(小时、分钟、秒、毫秒)。

显示的值取决于您正在使用的客户端。 在 ArcGIS Online 中,将以您的组织或配置文件的本地时间来显示时间。

EXTRACT(<unit> FROM <date>)

返回指定 <date> 的单个部分 (<unit>)。 可能的 <unit> 值包括但不限于 yearmonthdayhourminute

以下示例从日期时间值 2016-12-21 15:11 中提取不同的单位:

  • EXTRACT(MONTH FROM TIMESTAMP '2016-12-21 15:11:00') - 返回 12。
  • EXTRACT(DAY FROM TIMESTAMP '2016-12-21 15:11:00') - 返回 21。
  • EXTRACT(HOUR FROM TIMESTAMP '2016-12-21 15:11:00') - 返回 15。

数值函数

函数描述

ABS(<number>)

返回所指定数值的绝对(正)值。

CAST(<number> AS FLOAT | INT)

将 number 转换为其他类型。 FLOAT 可将指定数值转换为双精度型,而 INT 可将其转换为整型。

在以下示例中,数字被转换为整数。 因为整数是整数,所以结果是 1424。 在第二个示例中,整数被转换为浮点数,结果为带有小数的数字 1424.0

  • CAST(1424.49 AS INT)
  • CAST(1424 AS FLOAT

CEILING(<number>)

返回大于或等于指定数值的最小整数。

以下示例返回 13:

CEILING(12.93)

COS(<number>)

返回 <number>(假设其为以弧度为单位的角)的三角余弦值。

FLOOR(<number>)

返回小于或等于指定数值的最大整数。

以下示例返回 12:

FLOOR(12.93)

LOG(<number>)

指定数值的自然对数。

LOG10(<number>)

指定数值以 10 为底的对数。

MOD(<number>, <n>)

返回被除数 (<number>) 除以除数 <n> 后的余数。 <n> 和 <number> 必须均为整型。

示例包括以下内容:

  • MOD(10, 4) - 结果为 2。
  • MOD(CAST(DBLFIELD AS INT), 4) - DBLFIELD 是双精度型字段,所以需使用 CAST 函数将值从双精度型转换为整型。

NULLIF(<number>, <value>)

若指定数值等于指定值,则返回 nullNULLIF 通常用于防止出现因将 <value> 设置为 0 而产生的除数为零的错误。

只要计算中任意参数出现 null 字段值,计算结果即为 null

例如,假设您需要将一个双精度字段的值换算成 TOTALPOP 除以 POP18。 如果任意要素的 POP18 值等于零,则计算将导致一个除数为零的错误。 您可以创建一个过滤器来隐藏 POP18 为零的那些记录,然后执行计算。 也可以使用捷径 NULLIF

TOTALPOP / NULLIF(POP18, 0) - 如果 POP18 等于 0,则返回 null;否则,返回 TOTALPOP / POP18 的值。

POWER(<number> , <y>)

返回指定数值的指定幂的值 (<y>)。

以下示例返回 32768:

POWER(8,5)

ROUND(<number> , <length>)

将所指定数值四舍五入至指定长度。

如果 <length> 使用正数,则数值将舍入到小数点右侧的小数位。 如果 <length> 为负数,则指定的 <number> 将舍入到小数点左侧的相应位置。

示例如下:

  • ROUND(10.9934,2) - 返回 10.99。
  • ROUND(10.9964,2) - 返回 11.00。
  • ROUND(111.0,-2) - 返回 100.00。

SIN(<number>)

返回指定 <number>(假设其为以弧度为单位的角)的三角正弦值。

TAN(<number>)

返回指定 <number>(假设其为以弧度为单位的角)的正切值。

TRUNCATE(<number>,<decimal_place>)

在指定 <decimal_place> 处截断 <number>

正的 <decimal_place> 将截断至指定的小数位。 若 <decimal_place> 为负数,将在小数点左侧的相应位置截断 <number>

在第一个示例中,小数点右边的数字被截断为仅包含两个数字,因此结果为值 111.99。 在第二个示例中,小数点左边的数字被截断,结果为值 100.00。

  • TRUNCATE(111.996,2)
  • TRUNCATE(111.996,-2)

字符串函数

函数描述

CAST(<string> AS DATE | TIME)

如果字符串值采用受支持的格式,则将字符串转换为日期或时间。

如果字符串的格式为“MM/DD/YYYY hh:MM:ss”或“YYYY-MM-DD”,则可以将其转换为日期。 如果字符串的格式为“HH:MM:SS”,则可以将其转换为仅时间数据类型 (TIME)。

例如,可以将以下字符串转换为日期:

CAST('1988-05-30' AS DATE)

CHAR_LENGTH(<string>)

返回指定字符串的字符数。 结果为整数。

例如,以下语句返回 8:

CHAR_LENGTH('Redlands')

CONCAT(<string1>, <string2>)

连接两个字符串值。

只能提供两个字符串。 要连接两个以上的字符串,需嵌套连续的 CONCAT 函数,如下所示。

以下第一个示例连接字母 A 和 B。 第二个示例显示嵌套 CONCAT 函数用于连接三个字符串值 A、: 和 B。

  • CONCAT('A', 'B') - 结果为 'AB'
  • CONCAT('A', CONCAT(':', 'B')) - 结果为 'A:B'

空值会转换成空字符串。

CURRENT_USER

CURRENT_USER 函数包含在查询中时,其作用类似于变量;访问托管要素图层或托管要素图层视图的用户的用户名在查询中识别和使用。

例如,如果用户 planner3 登录到组织以访问包含以下查询定义的托管要素图层视图,则只有 staffmember 字段包含值 planner3 的要素返回到连接用户:

staffmember=current_user

在下一示例中,staffmember 字段中存储了多个值。 即使字段中存储了多个用户名,以下 where 子句也会在 staffmember 字段的文本值中查找当前用户名:

where=position(current_user in staffmember)>0

POSITION(<substring>, <string>)

返回所指定字符串中指定子字符串第一次出现时的位置。 如果没有找到指定的子字符串,则结果为 0。

在下面的第一个示例中,结果是 5,因为子字符串 (boat) 的第一个字母 (b) 是字符串 (Sailboat) 中的第五个字母。 在第二个示例中,结果为 0,因为字符串中不存在子字符串 (motor)。

  • POSITION('boat', 'Sailboat')
  • POSITION('motor', 'Sailboat')

SUBSTRING(<string>, <start>, <length>)

返回部分字符串值;<start> 是一个整数索引,用于指定所返回字符的起始位置,<length> 则为返回的字符数。

请参阅以下示例:

  • SUBSTRING('Sailboat', 5, 4) - 结果为 'boat'
  • SUBSTRING('Sailboat', 1, 4) - 结果为 'Sail'
  • SUBSTRING('Sailboat', 5, 100) - 结果为 'boat'

TRIM(BOTH | LEADING | TRAILING ' ' FROM <string>)

返回从所指定字符串中移除所有前导或尾随空格后的字符串。

在以下示例中,字符串 San Bernardino 前后均有一个空格。 关键字 BOTH 用于从文本字符串的开始和结束处修剪空格字符串(用两个单引号表示,中间有一个空格):

TRIM(BOTH ' ' FROM ' San Bernardino ')

这将返回字符串 'San Bernardino'

UPPER(<string>)

返回所有字符转换成大写后的字符串。

在此示例中,字符串 Sailboat 中的所有字母均转换为大写,从而得到字符串 'SAILBOAT'

UPPER('Sailboat')

LOWER(<string>)

返回所有字符转换成小写后的字符串。

在下一示例中,返回 'sailboat'

LOWER('Sailboat')