RelationalData#

class sdm.relational.RelationalData(tables: Mapping[str, TableTensor], relationships: Collection[Relationship | Mapping[str, str | Sequence[str]]])#

Bases: DeviceMixin

Collection of named tables and join relationships.

from sdm import RelationalData, TableTensor

data = RelationalData(
    tables={
        "users": TableTensor.from_columns(
            {"user_id": [0, 1]},
            stypes={"user_id": "id"},
        ),
        "orders": TableTensor.from_columns(
            {
                "user_id": [0, 1],
                "item_id": [10, 11],
            },
            stypes={
                "user_id": "id",
                "item_id": "id",
            },
        ),
        "items": TableTensor.from_columns(
            {"item_id": [10, 11]},
            stypes={"item_id": "id"},
        ),
    },
    relationships=[
        # Foreign key from orders to users:
        dict(left_table="orders", left_column="user_id", right_table="users", right_column="user_id"),
        # Foreign key from orders to items:
        dict(left_table="orders", left_column="item_id", right_table="items", right_column="item_id"),
    ],
)
Parameters:
edge_indices(dtype: dtype | None = None, device: device | str | None = None) → tuple[Tensor, ...]#

Materialize heterogeneous graph edges for table relationships.

Parameters:
  • dtype (dtype | None) – The dtype.

  • device (device | str | None) – The device.

Returns:

The edge indices for each relationship in order. Each edge index has shape [2, num_edges] and stores left table indices in the first row and right table indices in the second row.

Return type:

tuple[Tensor, …]

sampler(time_columns: Mapping[str, str] | None = None) → RelationalSampler#

Create a device-appropriate sampler over this relational data.

import sdm

data = sdm.RelationalData(
    tables={
        "users": sdm.TableTensor.from_columns(
            {"user_id": [0, 1]},
            stypes={"user_id": "id"},
        ),
        "orders": sdm.TableTensor.from_columns(
            {
                "user_id": [0, 1],
                "item_id": [10, 11],
                "order_date": ["2026-01-01", "2026-01-02"],
            },
            stypes={
                "user_id": "id",
                "item_id": "id",
                "order_date": "datetime",
            },
        ),
        "items": sdm.TableTensor.from_columns(
            {"item_id": [10, 11]},
            stypes={"item_id": "id"},
        ),
    },
    relationships=[
        # Foreign key from orders to users:
        dict(left_table="orders", left_column="user_id", right_table="users", right_column="user_id"),
        # Foreign key from orders to items:
        dict(left_table="orders", left_column="item_id", right_table="items", right_column="item_id"),
    ],
)

sampler = data.sampler(time_columns={"orders": "order_date"})
Parameters:

time_columns (Mapping[str, str] | None) – Mapping from table name to the datetime column used for temporal sampling. A row in a time-aware table can only be sampled if its timestamp does not exceed the query timestamp.

Return type:

RelationalSampler

to_graphviz(*, hide_columns: bool = False, **kwargs: Any) → graphviz.Graph#

Return a graph visualization of the relational schema.

Parameters:
  • hide_columns (bool) – Whether to hide column name descriptions.

  • **kwargs (Any) – Additional keyword arguments passed to graphviz.Graph.

Return type:

graphviz.Graph