# STATS

The `STATS` command in ES|QL is a processing command that groups rows according to a common value and calculates one or more aggregated values over the grouped rows. If `BY` is omitted, the output table contains exactly one row with the aggregations applied over the entire dataset.

The following aggregation functions are supported:

- `AVG`
- `COUNT`
- `COUNT_DISTINCT`
- `MAX`
- `MEDIAN`
- `MEDIAN_ABSOLUTE_DEVIATION`
- `MIN`
- `PERCENTILE`
- `ST_CENTROID_AGG` (This functionality is in technical preview and may be changed or removed in a future release)
- `SUM`
- `VALUES`

It's important to note that `STATS` without any groups is much faster than adding a group. Grouping on a single expression is currently much more optimized than grouping on many expressions. 

## Examples

Here are some examples of how you can use the `STATS` command in ES|QL:

1. Calculating a statistic and grouping by the values of another column:

    ```esql
FROM employees
| STATS count = COUNT(emp_no) BY languages
| SORT languages
```

2. Omitting `BY` returns one row with the aggregations applied over the entire dataset:

    ```esql
FROM employees
| STATS avg_lang = AVG(languages)
```

3. It’s possible to calculate multiple values:

    ```esql
FROM employees
| STATS avg_lang = AVG(languages), max_lang = MAX(languages)
```

4. It’s also possible to group by multiple values (only supported for long and keyword family fields):

    ```esql
FROM employees
| EVAL hired = DATE_FORMAT("YYYY", hire_date)
| STATS avg_salary = AVG(salary) BY hired, languages.long
| EVAL avg_salary = ROUND(avg_salary)
| SORT hired, languages.long
```

5. Both the aggregating functions and the grouping expressions accept other functions. This is useful for using `STATS...BY` on multivalue columns. For example, to calculate the average salary change, you can use `MV_AVG` to first average the multiple values per employee, and use the result with the `AVG` function:

    ```esql
FROM employees
| STATS avg_salary_change = ROUND(AVG(MV_AVG(salary_change)), 10)
```

6. An example of grouping by an expression is grouping employees on the first letter of their last name:

    ```esql
FROM employees
| STATS my_count = COUNT() BY LEFT(last_name, 1)
| SORT `LEFT(last_name, 1)`
```

7. Specifying the output column name is optional. If not specified, the new column name is equal to the expression. The following query returns a column named `AVG(salary)`:

    ```esql
FROM employees
| STATS AVG(salary)
| EVAL avg_salary_rounded = ROUND(`AVG(salary)`)
```

## Limitations

- `STATS` does not support configurations where the `_source` field is disabled.
- Full-text search is not supported.
- `text` fields behave like `keyword` fields.
- Time series data streams are not supported.
- Date math expressions work well when the leftmost expression is a datetime.
- Enrich limitations: The ES|QL `ENRICH` command only supports enrich policies of type `match`. Furthermore, `ENRICH` only supports enriching on a column of type `keyword`.
- Dissect limitations: The `DISSECT` command does not support reference keys.
- Grok limitations: The `GROK` command does not support configuring custom patterns, or multiple patterns. The `GROK` command is not subject to Grok watchdog settings.
- Multivalue limitations: ES|QL supports multivalued fields, but functions return `null` when applied to a multivalued field, unless documented otherwise.
- Timezone support: ES|QL only supports the UTC timezone.
- Kibana limitations: The user interface to filter data is not enabled when Discover is in ES|QL mode. To filter data, write a query that uses the `WHERE` command instead. Discover shows no more than 10,000 rows. This limit only applies to the number of rows that are retrieved by the query and displayed in Discover. Queries and aggregations run on the full data set. Discover shows no more than 50 columns. If a query returns more than 50 columns, Discover only shows the first 50. CSV export from Discover shows no more than 10,000 rows. This limit only applies to the number of rows that are retrieved by the query and displayed in Discover. Queries and aggregations run on the full data set. Querying many indices at once without any filters can cause an error in kibana which looks like `[esql] > Unexpected error from Elasticsearch: The content length (536885793) is bigger than the maximum allowed string (536870888)`. The response from ES|QL is too long. Use `DROP` or `KEEP` to limit the number of fields returned.