# Relations and formulas

_Connect databases to each other and compute values from your fields._

Canonical: https://snoze.dev/help/relations-and-formulas/

Databases get powerful when they stop being islands. **Relations** connect
records across databases; **formulas** compute new values out of the fields
you already have.

## Relations

A relation field links records in one database to records in another —
tasks to a project, deals to a company, invoices to a client.

- Add a field with type **Relation** and pick the database it points to.
- On each record, the field holds one or more linked records, picked from a
  search.
- The link is two-way: the related database gets a mirror field showing the
  connection from its side.

Once related, a project's page can show its tasks, and each task knows its
project — the structure mirrors how the work actually connects.

## Formulas

A formula field computes its value from other fields on the same record —
it's read-only and always up to date.

- Arithmetic and text: `price * quantity`, joining a first and last name
- Dates: days until a deadline, age of a record
- Conditions: label a task "Overdue" when the due date has passed
- Across relations: pull in or aggregate values from linked records — a
  project's task count, the total of its invoices
- Across the whole database: totals, shares, and values from one specific
  record with `column` and `lookup`
- Lists and composition: transform, filter, find, or test related values with
  `map`, `filter`, `find`, `some`, and `every`
- People and records: read structured IDs, names, emails, and object properties
- Typed results: return numbers, text, checkboxes, dates, date ranges, lists,
  people, records, rich text, or JSON

The formula editor is designed to be explored rather than memorized. Type a
property or function name for autocomplete, or insert one from the searchable
library. Properties appear by their familiar labels, errors point to the exact
part that needs attention, and a live preview shows the result before you save.
Arithmetic supports the usual `+`, `-`, `*`, `/`, `%`, and `^` operators, while
the function library covers conditions, text, dates, lists, aggregates,
trigonometry, logarithms, regex text tools, people, records, and rich output.

Use `current` and `index` inside list functions:

```js
map(related(projects, budget), round(current * 1.1, 2))
```

Use `relatedRecords(projects)` when you need linked record IDs or titles;
`related(projects, budget)` remains the explicit, permission-scoped way to
read a target property.

### Reading other records in the same database

`column(property)` returns that property's value on every record in the
database, oldest first, so the usual list functions work on a whole column:

```js
amount / sum(column(amount)) // this record's share of the total
count(filter(column(status), current == "Done"))
```

`lookup` reads one property from one other record. Give it a record's name
and the property to return, or, with three arguments, a property to match
first:

```js
lookup("Gold", price) // Price on the record named Gold
quantity * lookup(code, currency, rate)
```

Records in Trash are left out. A formula that uses `column` or `lookup`
updates whenever any record in the database changes, so it can't be read by
another `column` or `lookup`, and the live preview shows its result only
after you save. Very large databases (more than 2,000 records) refresh these
formulas in the background within a few seconds. `column` and `lookup` read
at most 10,000 records; in a larger database these formulas are empty. The
result is copied to every record, so it can be up to 1,000 characters: use
`sum`, `count` or `join` on a whole column rather than returning the list.
Totals are worked out once for the whole database, but a formula that
compares each record with a whole column, such as a rank, does work for
every pair of records; it stays empty in databases of more than about 1,500
records.

Use `let` or `lets` when an intermediate value has a useful name:

```js
lets(subtotal, price * quantity, tax, subtotal * 0.2, subtotal + tax)
```

Conditions can use either `if(...)`, `ifs(...)`, or the compact
`condition ? value : fallback` form. Open **Guide** in the editor and search a
function to see its syntax, description, example, and insert it directly.

## Together

The pattern that carries most teams: one database per real-world thing
(projects, tasks, people, clients), relations to express how they connect,
and a few formulas for the numbers you keep re-computing by hand. Views over
that — covered in [Views and filters](https://snoze.dev/help/views-and-filters/) — do the
rest.

> [!NOTE]
> A formula updates the moment any field it depends on changes, including
> fields on related records. If a number looks stale, check whether a filter
> is hiding the records feeding it.