CSV Window Functions

Add SQL-style window columns to a CSV without collapsing rows: running total, moving average, lag/lead, rank, dense_rank, and row_number — grouped by partition and ordered however you like.

Try:
Result CSV

About this CSV window-function tool

Window functions compute a value across a set of rows that are related to the current row, without collapsing those rows the way GROUP BY does. This tool brings the SQL OVER (PARTITION BY … ORDER BY …) idea to a plain CSV: every input row is kept, and one new column is appended with the window result.

Pick a function, choose the value column by header name (for example sales) or 1-based index (for example 3), and optionally partition and order the rows:

region,day,sales
W,2,5
E,1,10
W,1,3
E,2,20

A running total of sales, partitioned by region and ordered by day, produces one cumulative column, with rows grouped by partition:

region,day,sales,running_total_sales
W,1,3,3
W,2,5,8
E,1,10,10
E,2,20,30

The functions

Partitions and order

partition_by splits the rows into independent windows — one per distinct combination of the listed columns — so a running total restarts for each region and a rank is computed group by group. order_by sorts rows within each partition before the function runs, which is what makes a running total or lag meaningful. Turn on Descending to reverse the sort and to rank the largest value first.

Numbers are detected automatically; blank or non-numeric cells are skipped by the numeric functions (running total, moving average) rather than treated as zero.

Everything runs locally in your browser. Your CSV data is never uploaded.

FAQ

What is the difference between rank and dense_rank?

Both give tied values the same rank. rank then leaves a gap — two values tied for 1st are followed by 3rd (1, 1, 3, 4). dense_rank never leaves gaps, so the next value is 2nd (1, 1, 2, 3). Use row_number when you want every row to get a distinct number even on ties.

How does the moving average handle the first few rows?

The window is trailing and includes the current row, so with window=3 the first row averages just itself, the second averages the first two, and from the third row on it averages the current row plus the two before it. Non-numeric cells in the frame are ignored, so a blank value does not drag the average toward zero.

Do I need to sort my CSV first?

No. Set order_by to the column that defines the sequence (such as a date or day number) and the tool sorts each partition for you before computing. Leave order_by empty to use the rows in their existing order. The output rows are grouped by partition and follow the order you chose.

Can I compute a window per group, like per customer or per region?

Yes. Put the grouping column(s) in partition_by — for example region, or region,category for a combined key. Each distinct combination becomes its own window, so running totals restart and ranks are computed within each group independently.

Why does the tool require a header row?

Columns are selected by header name (with 1-based index as a fallback), and the appended column needs a header too. Keep the first row as your header. You can still reference columns by number, such as 3, if your headers are not descriptive.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool csv-window-functions "region,day,sales
W,1,3
W,2,5
E,1,10
E,2,20"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/csv-window-functions/?data=region%2Cday%2Csales%0AW%2C1%2C3%0AW%2C2%2C5%0AE%2C1%2C10%0AE%2C2%2C20&function=running_total&column=sales&partition_by=region&order_by=day&window=3&offset=1&output_column=running_total_sales&descending=true&has_header=true&delimiter=%2C

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.