Joining tables in Qlik Sense can be powerful but tricky, especially when handling large datasets and optimizing performance. This guide explains Inner, Left, Right, and Outer Joins, when to use Keep and ApplyMap instead, and best practices to avoid common pitfalls like data loss or slow reloads. Master the right approach to efficiently merge data in Qlik Sense without bloating your data model.
Explore B EYE’s Qlik Services
When working with Qlik Sense, one of the most powerful but potentially tricky aspects is joining tables. Unlike a typical SQL environment, Qlik Sense uses an associative model designed to automatically link tables on common fields. Still, there are times when you need to explicitly merge data sets. In this article, we’ll explore:
- What joins are and how Qlik Sense handles them
- When to use or avoid joins (and potential alternatives like Keep or ApplyMap)
- Performance considerations, common pitfalls, and best practices
Whether you’re integrating large fact tables or enriching dimension data, understanding Qlik Sense joins thoroughly can save you from data loss, slow reload times, and modelling headaches. Let’s dive in!
Before explaining each join type, it helps to distinguish Join, Keep, and Concatenate in Qlik Sense. Although all can combine data, each serves a different purpose:
A good rule of thumb:
- Join when you need extra columns or values in the target table.
- Keep when you want to filter data across multiple tables but still keep them separate.
- Concatenate when you’re main goal is to add rows, not columns.
Like SQL, Qlik Sense supports Inner, Left, Right, and Outer joins. The syntax, however, comes as a prefix in the load script.
Inner Join
- Definition: Only matching rows from both tables are combined.
- Use Case Example: Filtering down Orders to only those Customers who exist in the Customers table.
In this script:
- We first load the Customers table.
- An Inner Join to Orders merges matching rows on CustomerID.
- Any order that doesn’t match an existing CustomerID is discarded.
Visual Example: If you had three customers (IDs 1, 2, and 3) but Orders only had IDs 2 and 3, the final table keeps just the matching rows (2 and 3).
Left Join
- Definition: All rows from the left (previously loaded) table, plus matching rows from the next table. Unmatched rows from the next table are dropped, but unmatched rows from the left table appear with NULL in joined columns.
- Use Case Example: Enriching a main fact table (Customers) with additional attributes (e.g., Loyalty Scores).
In this script:
- The Customers table remains unchanged.
- Every customer row is preserved; if a LoyaltyScore can’t be matched, that field appears as NULL.
Why This Matters: Advanced Qlik users often do Left Joins to enrich a primary dimension table with optional attributes. Just be aware that any record in the second table not found in the Customers table is lost.
Right Join
- Definition: All rows from the right (second loaded) table, plus matching rows from the first table. Unmatched rows from the first table are discarded.
- Use Case Example: Filtering a dimension table down to only rows that exist in a target table.
In this script:
- Goal: Keep only Car IDs that have a SalesTarget, discarding rows from Sales if no matching target is found.
- This is effectively a “hard filter” on the first table based on the second.
Important Note: The order in which you load tables is crucial. If you swapped the order here, you’d get a Left Join result (which might not filter out all non-target Car IDs).
Outer Join
- Definition: All rows from both tables, matched where possible. If a row only appears in one table, that row is still included (NULLs for the other table’s fields).
- Use Case Example: Combining two customer lists from different systems while retaining all unique customers.
In this script:
- You end up with every CustomerID from both data sources in one table.
For advanced users, understanding the impact of joins on performance is crucial:
- Large Fact Tables: Joining big tables can multiply rows if there are multiple matching keys (a cartesian effect). This can bloat the data model and slow down reloads.
- Associative Model: Qlik Sense is designed to link tables on matching field names. Usually, it’s more efficient to leave the tables separate and let Qlik’s engine handle associations.
- Use Keep Instead: If you only need to filter data without merging columns, Keep can preserve separate tables, lowering memory usage.
Best Practice: Always validate row counts before and after a join. If a table grows unexpectedly large, you might be joining on too many common fields or the wrong field altogether.
Sometimes, the best join is no join at all. Here are scenarios where you might avoid explicit joins in favour of other techniques:
- If you just need a single field from a small lookup table, mapping (ApplyMap) is often more efficient.
- Example: Merging a CategoryName from a small category table into a large Sales table without fully joining them.
- Use Inner Keep, Left Keep, or Right Keep to filter multiple tables at once while preserving separate structures.
- Good for advanced data modelling where you need relational filtering but still want the flexibility of distinct tables.
- .Qualify or Composite Keys
- If you have multiple common fields between two tables, consider qualifying field names or creating a composite key. This avoids unexpected merges or synthetic keys.
- Example: Region & ‘|’ & Country as Key_SalesRegion
Performance Tip: Qlik’s documentation recommends limiting heavy script joins whenever possible. Keeping data separate typically leverages the associative model, which is faster and more flexible.
Let’s see how a Right Join can be used in a business scenario. Suppose you have:
- Sales table with columns: ItemID, SalesDate, QuantitySold.
- Targets table with columns: ItemID, YearlyTarget.
You only want items that have a YearlyTarget.
In this script:
- This approach keeps all target items, even if the Sales table lacks certain rows (e.g., new items introduced mid-year).
- Any item not listed in TargetData is removed from the final Sales table.
Result: A streamlined table containing just the targeted items and their sales figures. This technique is especially helpful if your organization frequently adds new product lines but only wants to analyze the ones with defined goals.
Even seasoned developers can run into problems. Here are a few frequent ones:
- Long Reload Times or App Freezes
- Cause: Potentially a cartesian product if you have multiple join fields with many repeating values.
- Solution: Confirm you’re joining on unique keys or reduce the join scope (consider Inner Keep or filtering fields).
- Cause: Using Inner Join or Left Join when you actually needed an Outer Join.
- Solution: Verify the join type. For dimension lookups, an Outer Join or separate association might be better.
- Synthetic Keys / Circular References
- Cause: Multiple tables share multiple fields. Qlik automatically creates synthetic keys or circular links.
- Solution: Use Qualify or rename fields to ensure only the intended key fields match, or consider building a composite key.
- Null Fields After Joining
- Cause: If a row from the second table doesn’t match the first (Left Join), that field becomes NULL.
- Solution: Double-check whether the mismatch is desired or a sign that the key fields don’t align (e.g., leading zero issues, data format mismatches).
Pro Tip: Always do a quick row count or comparison after a join. If you notice a significant drop in records (or a massive increase), investigate immediately.
Below is a distilled checklist for reference:
- Specify the Join Type: Always use Inner Join, Left Join, etc. explicitly.
- Validate Keys: Make sure the fields you’re joining on match in both name and content.
- Minimize Large Joins: For massive tables, consider an alternative (Keep, ApplyMap, or Qlik associations).
- One Fact Table Strategy: Typically, design a star schema with one main fact table and multiple dimension tables. Don’t force all data into one big table.
- Check Row Counts: Use quick summary checks (counts, sums) before/after joins to avoid unexpected data loss or duplication.
- Leverage Mapping: For single-column lookups, use ApplyMap() instead of a join.
- Beware Multiple Fields: Multiple keys can lead to synthetic keys or larger tables. Use composite keys or rename/qualify.
By following these guidelines, you’ll sidestep common performance pitfalls and maintain a cleaner data model. Happy QlikSensing!