Intermediate · Lesson 11 of 22

Lookup Columns & Cross-Table References

Pull fields from related rows, count tasks per project, wire two-way linked relations, and embed subtables — so your tables always have the context they need without duplicating data.

⏱ ~28 min 🔗 Relations & lookups ✅ Prerequisite: Lesson 04
01 — Relation Columns Recap 02 — Lookup: Dot Notation 03 — RelatedRows Filter Pattern 04 — Two-Way Linked Relations 05 — Subtables 06 — Gotcha & CRM Example Practice
01 — Relation Columns Recap

A pointer to a row — not a text copy.

A Relation column stores a reference to a row in another table — not a copied text string. To set one up: click a column header → change type to Relation → choose the target table. The cell shows the target row's display column as a clickable pill. Why this matters: rename the target row once, and that name updates everywhere the relation is used. No stale copies, no manual find-and-replace.

Tasks — Project column is a Relation, not Text
Task Project Relation Status Select Due Date Date
Write landing copy Website Redesign In Progress Apr 20
Create Figma frames Website Redesign To Do Apr 25
Record demo video Product Launch To Do Apr 30
The Project column stores a reference to a row in the Projects table. If "Website Redesign" is renamed to "Web Relaunch" in Projects, all three task pills update instantly.
Why relations beat copy-pasting If you typed "Website Redesign" as plain text in every task row, you'd have to update every row when the project was renamed. With a Relation column there is a single source of truth — the Projects row. Change it once, it propagates everywhere automatically.
02 — Lookup: Dot Notation

Follow the pointer, grab a field.

Once a Relation column exists, pull any field from the related row using dot notation. These are "virtual" derived columns — they compute from the relation automatically and update whenever the source row changes.

thisRow.[Project].[Owner]
thisRow The current row in the Tasks table
[Project] The Relation column — "steps into" the related Projects row
[Owner] The field to pull from the Projects row — any column works

You can chain any column from the related row: thisRow.[Project].[Due Date], thisRow.[Project].[Status], and so on. Each lookup column is read-only — to change the value, edit the source row in the related table.

Tasks — Project Owner and Project Status pulled via dot notation
Task Project Relation Project Owner Lookup Project Status Lookup
Write landing copy Website Redesign Amara Osei In Progress
Create Figma frames Website Redesign Amara Osei In Progress
Record demo video Product Launch Priya Mehta To Do
Project Owner: thisRow.[Project].[Owner]
Project Status: thisRow.[Project].[Status]
Lookup columns are read-only You can't type into a Lookup column — the value is computed. To change it, edit the source field in the related table. This enforces a single source of truth and prevents conflicting edits.
03 — RelatedRows Filter Pattern

From the parent side — aggregate all related rows.

Sections 01–02 looked up data from child to parent (Task → Project). Now flip it: from the Projects table, get all tasks that belong to each project using a filter on the Tasks table, then chain aggregate functions.

Formula column in Projects table — returns a list of related Task rows
Tasks.Filter([Project] = thisRow)

From there, chain additional operations to produce the numbers your dashboard needs:

Aggregate patterns — chain onto the Filter result
// Task count per project
Tasks.Filter([Project] = thisRow).Count()

// Total estimated hours
Tasks.Filter([Project] = thisRow).Sum([Estimate])

// Completed task count
Tasks.Filter([Project] = thisRow).Filter([Done] = true).Count()

// Overdue open tasks
Tasks.Filter([Project] = thisRow)
     .Filter([Done] = false)
     .Filter([Due Date] < Today())
     .Count()
Projects — aggregate formula columns
Project Total Tasks Formula Total Estimate Formula Done Formula Overdue Formula
Website Redesign 8 42 hrs 3 2
Product Launch 12 68 hrs 9 0
04 — Two-Way Linked Relations

Bidirectional sync — Coda wires it automatically.

When you set up a Relation column in Tasks pointing at Projects, Coda automatically creates a corresponding linked relation column in Projects. No formula needed — Coda maintains both directions. Edit a task's project in either table and both stay in sync.

What you set up (Tasks table)

Add a Project Relation column in Tasks pointing at the Projects table.

Tasks.Project → Projects

What Coda creates automatically (Projects table)

A Tasks linked relation column in Projects appears, showing all task rows that reference each project.

Projects.Tasks ← auto-created

This enables bidirectional navigation: from a project row you can see and open all its tasks; from a task row you can navigate directly to its project. No formula column required for either direction.

Linked relation vs. formula column The auto-created reverse column is a linked relation — managed by Coda, always up to date. You can still add your own formula column (Section 03 pattern) if you want filtering or aggregation logic on top of the related rows.
05 — Subtables

Embed related rows inside a row's detail view.

A Subtable block shows related rows as an inline editable mini-table inside a canvas column or a row's expanded detail view. Add a Subtable → choose the relation column → related rows appear. Best for viewing a task list inside a project detail view without leaving the row.

Projects row detail — Tasks subtable embedded
Website Redesign Owner: Amara Osei
Tasks — 8 rows
TaskStatusDue Date
Write landing copy In Progress Apr 20
Create Figma frames To Do Apr 25
+ 6 more rows…
The embedded subtable is fully interactive — add, edit, and delete rows from within the parent row's detail view. It's row-scoped and lightweight, unlike embedding a full table view on a canvas page.
Subtable vs. embedding a full view A subtable is row-scoped: it only shows rows related to the open parent row. A full embedded view shows all rows in the table (which you then filter). Use subtables inside detail views; use embedded views on dashboard pages.
06 — Gotcha & CRM Example

Relation column first — then dot notation.

The most common mistake: writing thisRow.[Project].[Owner] in a table where Project is a plain Text column. You can't "dot into" a string. The formula will error. Fix: open the column settings, change type to Relation → Projects, then the lookup works.

Won't work

Project column is Text type. thisRow.[Project].[Owner] throws an error — can't reference fields from a text value.

✖ Column type: Text — dot notation not available

Works correctly

Change Project to Relation → Projects. Now thisRow.[Project].[Owner] follows the link and retrieves the field.

✔ Column type: Relation (→ Projects) — lookups work

Full CRM example: a Contacts table with a Company Relation column pointing at a Companies table. Derived columns pull Company data through automatically.

Contacts — Company relation + Lookup columns
Contact Company Relation Industry Lookup ARR Lookup Owner Lookup
James Mwangi Aether Systems SaaS $12M Priya Mehta
Sophia Kamau Aether Systems SaaS $12M Priya Mehta
David Okonkwo Horizon Retail E-commerce $4.2M Sam Torres
Industry: thisRow.[Company].[Industry]
ARR: thisRow.[Company].[ARR]
Contacts at this company (in Companies table): Contacts.Filter([Company]=thisRow).Count()
Practice

Test your knowledge.

Lookup Columns & Cross-Table References

5 Questions
Question 1 of 5
A Relation column stores a reference to a row in another table. What does a plain Text column named "Project" store instead?
A Text column stores a plain string — there is no live pointer to another table row. That's why dot-notation lookups don't work on Text columns. A Relation column stores an actual row reference, enabling thisRow.[Project].[Owner] and similar formulas.
Question 2 of 5
What is the correct dot-notation formula to pull the Due Date from a related Project row into a Tasks formula column?
thisRow.[Project].[Due Date] is the correct pattern: step into the Relation column [Project], then access the [Due Date] field on the referenced Projects row. There is no Lookup() function in Coda.
Question 3 of 5
You want a formula column in the Projects table that counts only the completed tasks for each project. Which formula is correct?
Tasks.Filter([Project] = thisRow).Filter([Done] = true).Count() chains two filters (scope to this project, then keep only done rows) before counting. You can also write both conditions inside one Filter: Tasks.Filter(And([Project] = thisRow, [Done] = true)).Count().
Question 4 of 5
When you create a Relation column in Tasks pointing at Projects, what does Coda automatically add to the Projects table?
Coda automatically creates a linked relation column in the target table (Projects) that shows all rows from the source table (Tasks) that reference each row. This two-way wiring happens automatically — no formula required.
Question 5 of 5
A subtable embedded in a row's detail view is best described as:
A subtable is row-scoped: it shows only the rows related to the currently open parent row, displayed as an inline editable mini-table. It's different from a full embedded table view (which shows all rows and requires a filter) and from a formula column (which produces a count or list, not an editable table).
← Prev Number & Date Formulas Lesson 10