The statistics query API allows you to get any of the following statistics for a specified field in a feature table: Sum, Average, Count, Minimum, Maximum, Standard Deviation, or Variance. In the statistics query parameters, you can define filters for features to include in the statistics (based on attributes, spatial relationships, or time extent) as well as how the results are grouped and sorted.

Follow these steps to query a feature table for statistical information:

- Load a feature table that supports statistical queries from a local or online data source. This may be a layer shown in a map view in your app, or a table you’ve loaded but not displayed.
`QUrl serviceUrl("https://sampleserver6.arcgisonline.com/arcgis/rest/services/SampleWorldCities/MapServer/0"); m_featureTable = new ServiceFeatureTable(serviceUrl, this); m_featureLayer = new FeatureLayer(m_featureTable, this); m_map->operationalLayers()->append(m_featureLayer); m_mapView->setMap(m_map);`

- Define statistics to return from the query. Create a StatisticDefinition for each statistic you want to query from the table. This includes the field name, statistic type, and output alias name for the result.
`QList<StatisticDefinition> definitions { // Construtor takes field name, statistics type, and field alias name (if any) StatisticDefinition("POP", StatisticType::Average, ""), StatisticDefinition("POP", StatisticType::Minimum, ""), StatisticDefinition("POP", StatisticType::Maximum, ""), StatisticDefinition("POP", StatisticType::Sum, ""), StatisticDefinition("POP", StatisticType::StandardDeviation, ""), StatisticDefinition("POP", StatisticType::Variance, ""), StatisticDefinition("POP", StatisticType::Count, "CityCount") };`

- Create a StatisticsQueryParameters object, passing in your list of (one or more) statistic definitions.
`StatisticsQueryParameters queryParameters; queryParameters.setStatisticDefinitions(definitions);`

- Define spatial, attribute, or temporal filters (if any) and add them to the query parameters.
Define an attribute filter.

`if (bigCitiesOnly) { queryParameters.setWhereClause("POP > 5000000"); }`

Define a spatial filter.

`if (extentOnly) { // Set the statistics query parameters geometry with the envelope queryParameters.setGeometry(m_mapView->currentViewpoint(ViewpointType::BoundingGeometry).targetGeometry()); // Set the spatial relationship to Intersects (which is the default) queryParameters.setSpatialRelationship(SpatialRelationship::Intersects); }`

- Specify the fields you want to group and order the results with.
`if (orderResults) { queryParameters.setOrderByFields(QList<OrderBy>() << OrderBy("MAX_POP", SortOrder::Descending)); } if (groupResults) { queryParameters.setGroupByFieldNames({"POP_RANK"}); }`

- Execute the query. The results are returned as a StatisticsQueryResult.
`m_featureTable->queryStatistics(queryParameters);`

- Iterate the result records to read the statistic values. The output alias name defined for each statistic definitions is the key for a corresponding value. If results were grouped, iterate the group names and associated collection of values.
`connect(m_featureTable, &ServiceFeatureTable::queryStatisticsCompleted, this, [this](QUuid, StatisticsQueryResult* result) { QObject parent; QString resultText(""); if (result) { // Iterate through the StatisticRecords in the StatisticsQueryResult StatisticRecordIterator iter = result->iterator(); while (iter.hasNext()) { StatisticRecord* statisticRecord = iter.next(&parent); int groupByColumnsCount = 0; // Number of group-by columns in results // If results are grouped, identify the group that this // StatisticRecord is for if (!statisticRecord->group().isEmpty()) // Results are grouped { const QVariantMap group = statisticRecord->group(); // Format group description, with a value for each group-by column for (auto iterGroup = group.cbegin(); iterGroup != group.cend(); ++iterGroup) { resultText += ((0 == groupByColumnsCount++) ? "[GROUP] " : " and ") + iterGroup.key() + " = " + iterGroup.value().toString() + "\n"; } } // Format statistics in this StatisticRecord const QVariantMap stats = statisticRecord->statistics(); for (auto iterStats = stats.cbegin(); iterStats != stats.cend(); ++iterStats) { resultText += ((0 == groupByColumnsCount) ? "" : "- ") + iterStats.key() + ": " + iterStats.value().toString() + "\n"; } // If results are from group-by query, separate groups with blank line if (0 != groupByColumnsCount) resultText += "\n"; } } else { resultText += "No results returned\n"; } emit showStatistics(resultText); delete result; });`

## Tables that support statistical queries

To see if a feature table supports a statistical query, check ArcGISFeatureLayerInfo::isSupportsStatistics for a feature layer or ArcGISMapServiceSublayerInfo::isSupportsStatistics for an ArcGIS map image sublayer.

##### Note:

If the **query** capability is disabled in the service capabilities, then statistics query is also disabled.

When using a service feature table (reading data from an online service, in other words), statistical queries are executed on the service unless the table is in **manual cache** mode, in which case the query executes on the locally available (cached) data. All other feature tables also execute statistical queries against a local data source.

## Define a statistics query

Use a StatisticsQueryParameters to define:

- Statistics to calculate and their output alias field names
- How results are grouped and ordered
- Filters that restrict which features are evaluated

Each of these are described in the following sections.

### Statistic definitions

A StatisticDefinition specifies the name of the field that contains values to query, the statistic type, and the output (alias) name to use for the results. A statistics query must contain at least one statistic definition, but may contain several. A field of any data type can be used for statistic types **Count**, **Minimum**, or **Maximum**, which will return the number of values, first value, or last value (when sorted in ascending order) respectively. Other statistic types: **Average**, **Sum**, **Standard Deviation**, and **Variance** are only valid for numeric fields. If these statistics are attempted on a non-numeric field, you will receive an error from the server ("unable to complete operation").

If the output statistic alias name is empty or missing, a default name will be assigned by the map server for the returned statistic field. The server-generated output name is composed of the field name and the statistic type separated by an underscore. If you specify a name, it can only contain alphanumeric characters and an underscore. If the output name is a reserved keyword of the underlying DBMS, the operation may fail.

### Group and order results

Unless otherwise specified, the results from a statistical query will not be grouped using a table attribute. In this case, the statistic values returned are single values that describe all the input features. If one or more group fields are specified, the results contain a value for each statistic for each group. If getting average population for world cities grouped by countries, for example, each country would have a value for the average population of their cities. Without this grouping, you would get a single value for all cities in the world.

Results are also not ordered unless you specify one or several fields to sort on. The fields you choose to order results by must be fields you've also chosen for grouping. The following example shows results for statistics on US states grouped by sub-region. The results are also sorted by sub-region (in ascending order).

### Filter features to evaluate

You can define any combination of spatial, attribute, or temporal criteria to filter the features that are evaluated by the statistical query. If none of these filters are set, the query will be evaluated against all features in the table.

**Attribute**—define a where expression that uses any of the fields in the table.**Spatial**—use a geometry object and a spatial relationship.**Temporal**—specify a time or time range.

## Process results from a statistical query

The results from a statistical query are returned as an enumerator of StatisticRecord objects. Each record describes a group and contains a dictionary of group values and a dictionary of statistic values. The group dictionary contains key/value pairs that describe each group field, with the field name ("SUB_REGION", for example) as the key for the field value ("Mountain", for example). Since multiple group fields can be specified for a query, each record in the results represents a unique combination of the group field values.

The statistics dictionary for each record contains the requested statistics for the group. The key for each statistic value is the alias name (by default, in the form **fieldName_statisticType**). If no group fields were specified for the query, the groups dictionary is empty and a single set of statistics are returned to describe all features included in the query.