Join this relation to another table using dlt schema references. Join conditions are discovered automatically from the schema's reference chain (parent/child/root relationships created by dlt during loading). Both the current relation and ``other`` must be base-table relatio
(
self,
other: str | Self,
*,
kind: TJoinType = "inner",
alias: Optional[str] = None,
)
| 369 | return rel |
| 370 | |
| 371 | def join( |
| 372 | self, |
| 373 | other: str | Self, |
| 374 | *, |
| 375 | kind: TJoinType = "inner", |
| 376 | alias: Optional[str] = None, |
| 377 | ) -> Self: |
| 378 | """Join this relation to another table using dlt schema references. |
| 379 | |
| 380 | Join conditions are discovered automatically from the schema's reference |
| 381 | chain (parent/child/root relationships created by dlt during loading). |
| 382 | Both the current relation and ``other`` must be base-table relations |
| 383 | (i.e., created via ``dataset[table_name]``, not transformed with |
| 384 | ``.select()``/``.where()`` etc.). |
| 385 | |
| 386 | This method is designed for the common case of navigating dlt's |
| 387 | built-in table hierarchy. For more complex join scenarios — such as |
| 388 | custom join predicates, joining on non-reference columns, self-joins, |
| 389 | or multi-way joins with mixed conditions — use ``Relation.to_ibis()`` |
| 390 | to obtain an ibis table expression and construct the join manually:: |
| 391 | |
| 392 | t1 = dataset["orders"].to_ibis() |
| 393 | t2 = dataset["products"].to_ibis() |
| 394 | joined = t1.join(t2, t1.product_id == t2.id, how="left") |
| 395 | |
| 396 | Args: |
| 397 | other: Table name or base-table relation to join. |
| 398 | kind: Type of SQL join: ``"inner"``, ``"left"``, ``"right"``, |
| 399 | or ``"full"``. |
| 400 | alias: Projection prefix for the joined table's columns. Columns |
| 401 | from ``other`` appear as ``{alias}__{column}``. Defaults to |
| 402 | the target table name. |
| 403 | |
| 404 | Returns: |
| 405 | A new relation with the join(s) applied and the target table's |
| 406 | columns appended to the projection. |
| 407 | |
| 408 | Raises: |
| 409 | ValueError: If schema references between the two tables cannot be |
| 410 | resolved, or if either relation is not join-eligible. |
| 411 | """ |
| 412 | if alias == "": |
| 413 | raise ValueError("`alias` must be a non-empty string when provided.") |
| 414 | |
| 415 | if not self._table_name: |
| 416 | raise ValueError("This relation has no base table to resolve references.") |
| 417 | |
| 418 | if isinstance(other, dlt.Relation): |
| 419 | # TODO: remove once we allow cross-dataset joins |
| 420 | if not ( |
| 421 | self._dataset.is_same_physical_destination(other._dataset) |
| 422 | and self._dataset.dataset_name == other._dataset.dataset_name |
| 423 | ): |
| 424 | raise ValueError( |
| 425 | "Cannot join relations from different datasets: " |
| 426 | f"'{other._dataset.dataset_name}' vs '{self._dataset.dataset_name}'" |
| 427 | ) |
| 428 | target_table = other._table_name |