UniversityAPI ReferenceAXEL Relationship Functions

AXEL Relationship Functions

API Reference
4 min read
Updated December 12, 2025

AXEL Relationship Functions

AXEL provides powerful relationship traversal features that allow you to work with data across multiple related forms. These functions enable you to follow relationships between records, aggregate data from related tables, and filter or group data based on related fields.

Overview

In Mars, forms can have relation fields that link to other forms. For example:

  • An Orders form might have a customer field linking to Customers
  • A Customers form might have a region field linking to Regions

AXEL's relationship functions let you traverse these connections to access data from related records.

Quick Reference

Function Purpose Example
RELATED() Get a single value from a related record RELATED(Customer[name], VIA(customer))
RELATEDTABLE() Get all records from a related table RELATEDTABLE(Orders, VIA(customer))
VIA() Specify the relationship path to traverse VIA(customer, region)
JOIN: LEFT Include all records, NULL for orphans (default) RELATED(Region[name], JOIN: LEFT)
JOIN: INNER Exclude records without relationships RELATED(Region[name], JOIN: INNER)
DEFAULT: Provide fallback value for orphan records RELATED(Region[name], DEFAULT: "Unassigned")

Feature Matrix

Feature RELATED RELATEDTABLE
Returns single value Yes No (returns table)
Returns multiple records No Yes
Supports VIA clause Yes Yes
Supports JOIN option Yes Yes
Supports DEFAULT value Yes No
Use in aggregations Yes Yes
Use in FILTER Yes Yes
Use in SUMMARIZE Yes Yes

When to Use Each Feature

  • A single column value from a related record
  • To add a column showing related data (e.g., customer name on orders)
  • To filter by a related field's value
  • To group results by a related field

Use RELATEDTABLE when you need:

  • All matching records from a related table
  • To count or sum values from multiple related records
  • To aggregate data from a one-to-many relationship

Use VIA when:

  • The relationship field name differs from the table name
  • You need to traverse multiple relationship hops
  • You want explicit control over the traversal path

Use JOIN: INNER when:

  • You want to exclude records without relationships
  • You're calculating aggregates and want to skip orphans
  • NULL values would skew your results

Use DEFAULT when:

  • You want a meaningful fallback for orphan records
  • You're displaying data and need user-friendly values
  • You want "Unassigned" or "Unknown" instead of blanks

Data Model Example

Throughout this documentation, we'll use this example data model:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Orders    │────>│  Products   │────>│ Categories  │────>│ Departments │
│             │     │             │     │             │     │             │
│ - amount    │     │ - name      │     │ - name      │     │ - name      │
│ - quantity  │     │ - price     │     │ - discount  │     │ - budget    │
│ - date      │     │ - stock     │     │             │     │             │
│ - product   │     │ - category  │     │ - department│     │             │
└─────────────┘     └─────────────┘     └─────────────┘     └─────────────┘
        │
        │
        v
┌─────────────┐     ┌─────────────┐
│  Customers  │────>│   Regions   │
│             │     │             │
│ - name      │     │ - name      │
│ - email     │     │ - manager   │
│ - region    │     │             │
└─────────────┘     └─────────────┘

Learn More

Explore each feature in detail:

Quick Examples

Get customer name for each order

ADDCOLUMNS(
  [Orders],
  "Customer Name", RELATED([Customers][name], VIA(customer))
)

Get region name (2-hop traversal)

RELATED([Regions][name], VIA(customer, region))

Count orders per customer with fallback

ADDCOLUMNS(
  [Customers],
  "Order Count", COUNTX(RELATEDTABLE([Orders], VIA(customer)), 1)
)

Filter orders by region

FILTER(
  [Orders],
  RELATED([Regions][name], VIA(customer, region)) = "North America"
)

Revenue by department (3-hop aggregation)

SUMMARIZE(
  [Orders],
  RELATED([Departments][name], VIA(product, category, department)),
  "Total Revenue", SUMX([Orders], [amount])
)