Computed Join FAQ
Answers to common questions about Computed Joins. Use the section closest to what you are working on.
Container Selection
Which containers can I pick as inputs?
Any profiled container in the datastore (tables, views, files), plus Computed Tables and Computed Files. Unprofiled containers do not appear; profile them first to use them as join inputs. This applies to the Left and Right dropdowns in pairwise mode and to each source's Container dropdown in SQL mode. See Supported Inputs.
Can I join containers from different datastores?
Yes. In pairwise mode the Right Container can point to a different datastore; in SQL mode each source can. The Computed Join itself lives under its parent datastore (the left container's datastore in pairwise mode, or the first source's datastore in SQL mode). You need at least Viewer permission on every other datastore an input reads from. Reporter on the parent datastore is enough to view the joined output once it exists, but not to use another datastore as an input. See Permissions.
Can a Computed Join be the input of another Computed Join?
No. A Computed Join cannot be a pairwise reference or a SQL-mode source of another Computed Join. To combine three or more sources, use SQL mode (which takes two or more sources directly), or materialize the first join's result as a Computed Table and use that Computed Table as an input to the next Computed Join. See Supported Inputs and Computed Tables.
Configuration and Validation
What's the difference between pairwise and SQL mode?
Pairwise mode joins exactly two containers on one field per side; you pick the fields, join type, prefixes, and clauses, and Qualytics builds the query. SQL mode joins two or more aliased sources with a Spark SQL query you write yourself, which is the way to express composite keys, more than two sources, CTEs, window functions, and aggregations. You choose the mode with the Editor Mode toggle when creating the join. In the UI the mode cannot change after the join is saved; to switch modes, delete the join and create a new one. See Introduction · Two Ways to Define a Join.
Can I use a composite (multi-column) join key?
Not in pairwise mode, which joins on a single field per side. Use SQL mode and write the full condition, for example ON a.k1 = b.k1 AND a.k2 = b.k2. See How It Works · SQL Mode.
How many sources can a Computed Join have?
A pairwise join has exactly two. A SQL-mode join has two or more, up to a configurable maximum (10 by default) that your administrator can adjust. See Supported Inputs · Number of Inputs.
What can I write in the SQL mode query, and what is rejected?
The query is Spark SQL over the source aliases and supports CTEs, GROUP BY, window functions, and joins across any number of sources. Rejected: statements that modify data, qualified or catalog table references (reference sources by alias only), and functions that run arbitrary code such as reflect and java_method. See How It Works · The Query Language and Restrictions.
Why is the Left Datastore locked in the form?
In pairwise mode, the Left Datastore is the datastore you opened to create the Computed Join, so you always know which datastore owns the join. Only the Right Datastore can be selected, and it can point to a different datastore. After the join is saved, neither side can be changed. In SQL mode there is no locked datastore: each source picks its own, and the join is created under the first source's datastore.
What does the Select Expression auto-fill with?
When you select both containers, the Select Expression auto-fills with every top-level field from both sides, prefixed with the configured left and right prefixes. Trim it to the columns you actually need before saving. See How It Works.
What happens when I change a Prefix?
Changing a Prefix rewrites every matching column reference in the Select Expression automatically. If you hand-edited the Select Expression with the old prefix, those references are rewritten too. See Best Practices · Prefixes.
Can I edit the inputs after the join is created?
In pairwise mode, no: the Left Container and Right Container are immutable after creation, so to change them you delete the join and create a new one. In SQL mode, you can edit the sources and the query when you edit the join. See Edit a Computed Join.
Which join types are supported?
Inner, Left, Right, and Outer (Full Outer). Pick the type from the Join Type dropdown when creating or editing the join. See How It Works.
Why isn't DISTINCT allowed in the Select Expression?
The validator rejects every form of DISTINCT in the Select Expression: the bare DISTINCT keyword, DISTINCT(col), aggregate forms (COUNT(DISTINCT col), SUM(DISTINCT col), AVG(DISTINCT col), MIN(DISTINCT col), MAX(DISTINCT col)), APPROX_COUNT_DISTINCT(col), and multi-column variants. To deduplicate results, replace DISTINCT col with explode(collect_set(col)), adding a GROUP BY only when the Select Expression still has non-aggregated columns. See Best Practices for the full recipe. This restriction applies to the pairwise Select Expression only; in SQL mode DISTINCT is allowed because the whole query is valid Spark SQL.
What's the difference between Validate and Save?
Validate runs the configuration and reports parse or schema errors without saving. Save runs the same validation, then persists the join if validation passes. Validate is useful when iterating on the Select Expression or Filter Clause before saving. See Create a Computed Join and Edit a Computed Join.
Permissions
Who can create a Computed Join?
Users with Editor permission on the parent datastore can create any Computed Join and can set the owner to any user. Users with Author permission can create Computed Joins they own; the owner is set to the user who creates the join, and only an Editor can reassign it later. In both cases, you also need at least Viewer permission on every other datastore an input reads from. The parent datastore is the left container's datastore in pairwise mode, or the first source's datastore in SQL mode. See API · Permissions.
Who can view a Computed Join?
Any user with at least Reporter permission on the datastore can view the Computed Join, its profile, and its anomalies. See API · Permissions.
Can an Author edit a Computed Join they don't own?
No. An Author can only edit Computed Joins they own. Editors can edit any Computed Join on the datastore. See API · Permissions.
Can an Author transfer ownership?
No. Only an Editor can reassign the owner of a Computed Join. See API · Permissions.
Execution
Can I run quality checks on a Computed Join?
Yes. A Computed Join supports the same quality checks as any other container. See How It Works.
Does a Computed Join count as a container?
Yes. The joined output appears under its parent datastore's container list with its own profile, anomalies, checks, and scan history. See Introduction.
What happens to a Computed Join if I delete one of its input containers?
The delete is blocked and a confirmation dialog lists the Computed Joins that depend on the input. Delete the Computed Joins first, then the input. This applies to any input in either mode, whether a pairwise reference or a SQL-mode source. See Delete a Computed Join.
What happens to the join's profile and anomalies when I delete it?
They are removed with the Computed Join. The source containers and their data are untouched. See Delete a Computed Join.
What happens when the schema of an input container changes?
When you next save or profile the Computed Join, the platform lists the dropped fields. Confirm Proceed Anyway in the UI (or set force_drop_fields=true in the API request) to apply the change. The dropped fields are marked missing, and their quality checks and anomalies are preserved until the fields reappear. See Edit a Computed Join and API.
Are Computed Joins incremental?
The join always reads its inputs in full at execution; the incremental setting does not prune what the inputs load. You can configure an Incremental Strategy and Incremental Field on the joined output so that downstream scans process only rows newer than the last run. This works in both modes. The incremental field must be a column the join produces: a Select Expression column in pairwise mode, or one of the query's output columns in SQL mode. See How It Works · Incremental Loading.
How do null keys behave?
In pairwise mode, rows where either side of the join key is null are dropped before matching, regardless of join type. A null on the left does not match a null on the right. This differs from standard SQL for Left, Right, and Outer joins, which would preserve unmatched rows. If you need standard SQL null-key behavior, pre-process each side as a Computed Table that fills null keys with a placeholder value. In SQL mode, null-key handling follows the JOIN ... ON condition you write, using standard Spark SQL semantics. See How It Works.