Flow reference: Storage & Databases

Sum / Average Records

Count, sum, average, min or max a field over matching records, optionally per group with a top list: revenue, best sellers (Bottly storage or your PostgreSQL).

Count, sum, average, min or max a field over matching records, optionally per group with a top list: revenue, best sellers (Bottly storage or your PostgreSQL).

When and how to use it

Connect the input from the preceding step on the path that should perform this operation.
Fill the fields with data available in the trigger's context.
Connect the needed outputs; an unconnected path cannot run later blocks.

Configuration fields

Database — database


Bottly storage keeps records on Bottly (plan row limits, Storage page with import/export). Your PostgreSQL writes to your own database instead: the table and column names are used exactly as written, and values are sent as text parameters.

Input: Fixed choice.

Editor guidance: Bottly storage is built in (plan row limits apply). Your PostgreSQL uses your own database: tables and columns are used by name, values are sent as text parameters.

Available choices (preserve the exact value):
`` — Bottly storage
postgres — Your PostgreSQL


Connection string (Your PostgreSQL) — connection


A postgres://user:password@host:5432/database URL, kept in a bot env secret such as {env.DATABASE_URL} rather than typed into the block. The host must be reachable on the public internet; TLS is used unless the URL ends with ?sslmode=disable (?sslmode=verify-full also checks the certificate).

Input: Text with variable suggestions.

Editor guidance: Only used with Your PostgreSQL. Empty uses {env.DATABASE_URL}. Keep it in an env secret, never typed here. The host must be public; TLS is used unless the URL says sslmode=disable.

Format example, not a ready value for your server: {env.DATABASE_URL}.


Table — table


Name the bot-owned record collection consistently, such as tickets. A typo addresses a different table, not an alias of the old one.

Input: Text.

Format example, not a ready value for your server: orders.

Default: orders.


Filters (one per line) — filters


One condition per line: field = value, or != > < >= <= and contains (case-insensitive). Every line must match; leave it empty for all records. Values that are both numbers compare as numbers (10 > 9), anything else as text, and a missing field counts as empty, so sold != yes also matches records that were never marked. Values may use variables such as {user.id}.

Input: Multiline text.

Format example, not a ready value for your server: status = paid.

Default: ``.


Operation — operation


Choose the specific operation first, then fill only the inputs it requires. Different operations can return different data and can have different side effects.

Input: Fixed choice.

Default: sum.

Available choices (preserve the exact value):
count — Count
sum — Sum
avg — Average
min — Minimum
max — Maximum


Field (numbers) — field


The stored field name to compare. Match the name used when creating the record.

Input: Text.

Format example, not a ready value for your server: price.

Default: price.


Group by field (optional) — groupBy


Optional field to group by: one result per value of this field, highest first, written to {agg.top} and {agg.0.key}/{agg.0.value}. Empty gives one total in {agg.result}.

Input: Text.

Format example, not a ready value for your server: product.

Default: ``.


Top groups (1-25) — top


How many groups to keep when grouping (1-25), highest result first.

Input: Number.

Default: 10.


Store as — storeAs


Choose a short result prefix such as result. Later blocks must use this same prefix and run after this block. It is not a Discord channel or a persistent table.

Input: Text.

Editor guidance: {agg.result}; with group by also {agg.top} (one "value: result" line each), {agg.0.key}, {agg.0.value}

Default: agg.

Outputs and next steps

out: Continue to the next step.

Read the result after this block, using its configured prefix and the fields supported by the selected operation. Do not assume every response has a text or id field.

Test and troubleshoot

Test a missing record, then save and read the same lookup value. Use a narrow filter for Update/Delete. Renaming a table or field changes where the lookup runs.

Save, validate and publish. Perform one real test and read the first relevant log error. [Testing](/docs/flow-testing) · [Variables](/docs/flow-variables) · [Permissions](/docs/flow-permissions).