# BUCKET

The `BUCKET` function creates groups of values—buckets—out of a datetime or numeric input. The size of the buckets can either be provided directly or chosen based on a recommended count and values range.

## Syntax

`BUCKET(field, buckets, from, to)`

### Parameters

#### `field`

A numeric or date expression from which to derive buckets.

#### `buckets`

The target number of buckets or the desired bucket size if the `from` and `to` parameters are omitted.

#### `from` (optional)

The start of the range. Can be a number, a date, or a date expressed as a string.

#### `to` (optional)

The end of the range. Can be a number, a date, or a date expressed as a string.

## Important notes:

BUCKET can operate in two modes:
- one where the bucket size is computed based on a bucket count recommendation and a range,
- and another where the bucket size is provided directly.

When the bucket size is provided directly for time interval, it is expressed as a **timespan literal**, e.g.
- GOOD: `BUCKET(@timestamp, 1 month)`
- BAD: `BUCKET(@timestamp, "month")`

## Examples

Using a target number of buckets, a start of a range, and an end of a range

```esql
FROM employees
| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
| STATS hire_date = MV_SORT(VALUES(hire_date)) BY month = BUCKET(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
| SORT hire_date
```

This example creates buckets for hire dates in 1985, aiming for 20 buckets. The actual number of buckets may vary depending on the range.

Combine BUCKET with an aggregation to create a histogram

```esql
FROM employees
| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
| STATS hires_per_month = COUNT(*) BY month = BUCKET(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
| SORT month
```

This example calculates the number of hires per month in 1985.

Asking for more buckets can result in a smaller range

```esql
FROM employees
| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
| STATS hires_per_week = COUNT(*) BY week = BUCKET(hire_date, 100, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
| SORT week
```

This example creates weekly buckets for hire dates in 1985, aiming for 100 buckets.

Providing the bucket size directly

```esql
FROM employees
| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
| STATS hires_per_week = COUNT(*) BY week = BUCKET(hire_date, 1 week)
| SORT week
```

This example creates weekly buckets for hire dates in 1985 by directly specifying the bucket size.

Creating a salary histogram

```esql
FROM employees
| STATS COUNT(*) BY bs = BUCKET(salary, 20, 25324, 74999)
| SORT bs
```

This example creates a histogram of salaries, dividing the range into 20 buckets.

Omitting the range when the bucket size is known

```esql
FROM employees
| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
| STATS c = COUNT(*) BY b = BUCKET(salary, 5000.)
| SORT b
```

This example creates salary buckets with a fixed size of 5000.

Create hourly buckets for the last 24 hours

```esql
FROM sample_data
| WHERE @timestamp >= NOW() - 1 day AND @timestamp < NOW()
| STATS COUNT(*) BY bucket = BUCKET(@timestamp, 25, NOW() - 1 day, NOW())
```

This example creates hourly buckets for the last 24 hours.

Create monthly buckets for the year 1985

```esql
FROM employees
| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
| STATS AVG(salary) BY bucket = BUCKET(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
| SORT bucket
```

This example calculates the average salary for each month in 1985.

Using BUCKET in both aggregating and grouping parts of STATS

```esql
FROM employees
| STATS s1 = b1 + 1, s2 = BUCKET(salary / 1000 + 999, 50.) + 2 BY b1 = BUCKET(salary / 100 + 99, 50.), b2 = BUCKET(salary / 1000 + 999, 50.)
| SORT b1, b2
| KEEP s1, b1, s2, b2
```

This example demonstrates advanced usage of `BUCKET` in both aggregation and grouping.

Adjusting bucket start value with an offset

```esql
FROM employees
| STATS dates = MV_SORT(VALUES(birth_date)) BY b = BUCKET(birth_date + 1 HOUR, 1 YEAR) - 1 HOUR
| EVAL d_count = MV_COUNT(dates)
| SORT d_count, b
| LIMIT 3
```

This example adjusts the bucket start value by adding and subtracting an offset.
