row_number (windowcomp) ↗
Use the row_number() function within the windowcomp stage to assign a unique sequential integer to each row within a partition, based on the specified sort order. The numbering starts at 1 for the first row in each partition. This is equivalent to ROW_NUMBER() OVER(...) in SQL.
Syntax
| windowcomp row_number() [by <partition_field1>, <partition_field2>, ...] sort [asc|desc] <sort_field1> [, [asc|desc] <sort_field2>, ...] [as <alias>]
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
partition_field |
any | No | One or more fields to partition the data by (equivalent to SQL PARTITION BY). |
sort_field |
any | Yes | One or more fields to define the order within each partition (equivalent to SQL ORDER BY). Required for numbering functions. Defaults to ascending. |
alias |
string | No | An alias for the output field. |
Returns
Type: integer
Description: The row_number() function returns a unique sequential integer (starting at 1) for each row within its partition, based on the sort order. Unlike rank(), every row receives a distinct number even when sort values are tied.
Usage notes
- Sort required: The
sortclause is mandatory for therow_number()function. - Numbering function:
row_number()is a numbering function and cannot be used with window frames (betweenclause). - Unique values: Unlike
rank(),row_number()always assigns unique sequential numbers. When rows have identical sort values, the assignment among tied rows is non-deterministic. - Deduplication:
row_number()is commonly used for deduplication by assigning row numbers within groups and then filtering forrow_number = 1. - 1-based indexing: Row numbering starts at 1, not 0.
Examples
Example 1: Number events chronologically per host
Goal: Assign a sequential number to each event per host, ordered by time.
XQL code:
dataset = xdr_data | windowcomp row_number() by agent_hostname sort asc _time as event_seq
Explanation: The row_number() function assigns a sequential number to each row within each agent_hostname partition, ordered by _time in ascending order.
Output:
| _TIME | AGENT_HOSTNAME | ALERT_SEVERITY | EVENT_SEQ |
|---|---|---|---|
| 2024-01-15 08:00:00 | workstation-1 | 3 | 1 |
| 2024-01-15 09:00:00 | workstation-1 | 7 | 2 |
| 2024-01-15 10:00:00 | workstation-1 | 5 | 3 |
| 2024-01-15 08:30:00 | workstation-2 | 2 | 1 |
| 2024-01-15 09:30:00 | workstation-2 | 4 | 2 |
Example 2: Deduplication — keep latest event per host
Goal: Keep only the most recent event for each host by using row_number() and filtering.
XQL code:
dataset = xdr_data | windowcomp row_number() by agent_hostname sort desc _time as rn | filter rn = 1 | fields - rn
Explanation: The row_number() function assigns 1 to the most recent event (sorted descending by _time) within each agent_hostname partition. The filter stage keeps only the first row per host, and fields - rn removes the helper column.
Output:
| _TIME | AGENT_HOSTNAME | ALERT_SEVERITY |
|---|---|---|
| 2024-01-15 10:00:00 | workstation-1 | 5 |
| 2024-01-15 09:30:00 | workstation-2 | 4 |
Example 3: Global row numbering
Goal: Assign a global sequential number to all events ordered by time.
XQL code:
dataset = xdr_data | windowcomp row_number() sort asc _time as global_row_num
Explanation: Without a by clause, the row_number() function assigns a unique sequential number to every row across the entire result set, ordered by _time.
Output:
| _TIME | AGENT_HOSTNAME | GLOBAL_ROW_NUM |
|---|---|---|
| 2024-01-15 08:00:00 | workstation-1 | 1 |
| 2024-01-15 08:30:00 | workstation-2 | 2 |
| 2024-01-15 09:00:00 | workstation-1 | 3 |
| 2024-01-15 09:30:00 | workstation-2 | 4 |
| 2024-01-15 10:00:00 | workstation-1 | 5 |
Related articles
- Stages:
windowcomp,dedup,sort - Functions:
rank() - Datasets:
xdr_data