DEV Community

Cover image for Qlik Sense Data Architect Certification: Six Load Scripts to Write Before the QSDA Exam
Palak Mazumdar
Palak Mazumdar

Posted on

Qlik Sense Data Architect Certification: Six Load Scripts to Write Before the QSDA Exam

The Qlik Sense Data Architect certification (QSDA) is a 50-question, 90-minute exam with a 62% passing score. Two of its five topic areas, Data Model Design and Data Transformations, carry 66% of the weight, and most of that work happens in the data load script.

So the plain way to check your readiness is to write the scripts. Below are six short ones. Five use inline data, so you can paste them into the Data load editor of an empty Qlik Sense app. The syntax follows Qlik's script reference for Qlik Cloud as it read on 13 October 2026.

What does the QSDA exam cover, in numbers?

It covers five topic areas, and the two about modelling and transforming data are the largest. Qlik lists them on its exam details page for the Data Architect certification, which also says the exam is platform-neutral: the content applies to client-managed Qlik Sense and to Qlik Cloud.

Topic area Weight About how many of 50 questions
Identify Requirements 20% 10
Data Connectivity 8% 4
Data Model Design 28% 14
Data Transformations 38% 19
Validation 6% 3

The question counts are our arithmetic on Qlik's weights, not figures Qlik publishes. Qlik also notes that exam content is updated from time to time and that the number and difficulty of questions may change.

Fifty squares, one per QSDA exam question, grouped into the five topic areas: Identify Requirements 20%, Data Connectivity 8%, Data Model Design 28%, Data Transformations 38%, Validation 6%

The recommended experience on the same page reads like a job description: writing load scripts and validating data, basic ETL, creating connections to data sources, understanding the QVD layer, and knowing SQL and relational databases. The six scripts below follow that list.

Why does a synthetic key appear, and how do you remove it?

A synthetic key appears when two tables share two or more fields. Load these two tables and open the data model viewer.

Sales:
LOAD * INLINE [
Region, Year, Month, Sales
North, 2026, May, 245
North, 2026, June, 127
South, 2026, June, 645
];

Budget:
LOAD * INLINE [
Region, Year, Month, Budget
North, 2026, May, 200
North, 2026, June, 150
South, 2026, June, 600
];
Enter fullscreen mode Exit fullscreen mode

Both tables hold Region, Year and Month, so Qlik Sense builds a $Syn 1 key and a $Syn 1 Table that stores every combination of the three. Qlik's page on how synthetic keys form and how to handle them says the key is sometimes correct, but that most times it is there because of an error in the script.

The fix that page suggests is to form your own key, typically by string concatenation inside AutoNumber.

Sales:
LOAD Region, Year, Month, Sales,
     AutoNumber(Region & '|' & Year & '|' & Month) AS RegionMonthKey
INLINE [
Region, Year, Month, Sales
North, 2026, May, 245
North, 2026, June, 127
South, 2026, June, 645
];

Budget:
LOAD Budget,
     AutoNumber(Region & '|' & Year & '|' & Month) AS RegionMonthKey
INLINE [
Region, Year, Month, Budget
North, 2026, May, 200
North, 2026, June, 150
South, 2026, June, 600
];
Enter fullscreen mode Exit fullscreen mode

Now only RegionMonthKey links the two tables, and the three descriptive fields live in Sales alone. One limit is worth remembering. AutoNumber hands out integers in the order values are read, so its keys only match between tables built in the same reload. For keys that must survive between reloads, for example in QVD files, Qlik points to the Hash128, Hash160 and Hash256 functions.

What turns three tidy tables into a circular reference?

A circular reference is a loop: there is more than one path of associations between two fields. No pair of tables below shares two fields, so there is no synthetic key, and the model is still wrong.

Orders:
LOAD * INLINE [
OrderID, CustomerID, Date, Amount
1, C1, 2026-05-02, 120
2, C2, 2026-05-03, 80
];

Customers:
LOAD * INLINE [
CustomerID, Region
C1, North
C2, South
];

Targets:
LOAD * INLINE [
Region, Date, Target
North, 2026-05-02, 100
South, 2026-05-03, 90
];
Enter fullscreen mode Exit fullscreen mode

Orders links to Customers on CustomerID, Customers links to Targets on Region, and Targets links back to Orders on Date. The reload completes, but the progress window reports a circular reference and the data model viewer draws the loop with dotted lines. Qlik's tutorial on resolving a circular reference gives the simplest way out: rename or remove one of the fields.

Targets:
LOAD Region,
     Date AS TargetDate,
     Target
INLINE [
Region, Date, Target
North, 2026-05-02, 100
South, 2026-05-03, 90
];
Enter fullscreen mode Exit fullscreen mode

The loop is gone, because Targets now reaches Orders by one path only, through Customers. The rename has a price: selecting an order date no longer filters the targets. If the business compares orders and targets by region and by day, the better design is one composite key built from Region and Date, as in the first script, with Region mapped into Orders first. That mapping is the next script.

When is ApplyMap a better choice than a join?

Use ApplyMap when you need one attribute from a lookup table and the row count of the fact table must not change.

RegionMap:
MAPPING LOAD * INLINE [
CustomerID, Region
C1, North
C2, South
];

Orders:
LOAD OrderID,
     CustomerID,
     ApplyMap('RegionMap', CustomerID, 'Unassigned') AS Region,
     Amount
INLINE [
OrderID, CustomerID, Amount
1, C1, 120
2, C2, 80
3, C9, 40
];
Enter fullscreen mode Exit fullscreen mode

Order 3 belongs to a customer the map does not know, so it gets Unassigned, the third argument. Leave that argument out and the function returns the input value as it is, here C9. A mapping table has two columns, comparison values first, and Qlik drops it automatically when the script ends. The model gains a field and no extra table.

A join behaves differently. Qlik's Join reference says the target table can end up with more or fewer records than it started with, depending on how unique the join values are. If C1 appeared twice in the lookup, a left join would write order 1 twice and every Sum(Amount) would be too high. ApplyMap returns one value for each row, so that cannot happen. The ApplyMap function reference adds one warning: do not give the output field the name of an input field, as in ApplyMap('Map', A) AS A.

How do you make missing values selectable in a filter?

First decide whether the value is a blank or a real NULL, because the two need different handling. A blank cell in a text file or an inline table arrives as an empty string, and an expression can replace it.

Customers:
LOAD CustomerID,
     If(Len(Trim(Segment)) = 0, 'No segment', Segment) AS Segment
INLINE [
CustomerID, Segment
C1, Retail
C2,
C3, Wholesale
];
Enter fullscreen mode Exit fullscreen mode

Len(Trim(Segment)) = 0 is true for an empty string, for a string of spaces and for NULL, so all three end up in one value that a user can click in a filter pane. Customer C2 now has the segment No segment.

Real NULLs come from other places: a database connection, a join, or a forced concatenation of tables with different fields. Qlik's notes on NULL value handling in the load script say these NULLs generally cannot be used for associations or selections unless the NullAsValue statement is used.

NullAsValue Segment;
SET NullValue = 'No segment';
Enter fullscreen mode Exit fullscreen mode

NullAsValue works as a switch. It applies to the loading statements that come after it, and NullAsNull turns it off again. NullValue is the text that replaces the NULLs in the listed fields.

How does an incremental load keep a reload short?

It reads only the new and changed rows from the database, takes everything else from a QVD file, and then writes the QVD again. This script needs a database connection, so it is the one you cannot simply paste and run. It adapts the insert and update case from Qlik's guide to incremental load with QVD files.

LIB CONNECT TO 'SalesDb';
LET vThisExecTime = Now();

Orders:
SQL SELECT OrderID, CustomerID, Amount, ModifiedAt
FROM Orders
WHERE ModifiedAt >= '$(vLastExecTime)';   // use your database's date syntax

Concatenate (Orders)
LOAD OrderID, CustomerID, Amount, ModifiedAt
FROM [lib://DataFiles/Orders.qvd] (qvd)
WHERE NOT Exists(OrderID);

IF ScriptErrorCount = 0 THEN
  STORE Orders INTO [lib://DataFiles/Orders.qvd] (qvd);
  LET vLastExecTime = vThisExecTime;
END IF
Enter fullscreen mode Exit fullscreen mode

Three details are worth being able to explain.

  • Order matters. The changed rows load first, so WHERE NOT Exists(OrderID) can skip the old version of every updated order when the QVD is read.
  • Qlik's guide says this WHERE clause forces the QVD to be read in standard mode instead of optimized mode. That is still much faster than reading the whole database.
  • The QVD and the timestamp are only written when the script ran without errors. Without that test, a failed reload would move vLastExecTime forward and the missed rows would never be fetched.

The first run needs a full load to create the QVD. Rows deleted in the source need one more step, an inner join against the current keys, which the same guide shows.

How do you match a sale to the territory that was valid on that day?

Use IntervalMatch with a key field. This is the slowly changing dimension case that the first topic area of the exam mentions: a sales rep moves from one territory to another, and each sale must keep the territory that was valid on the sale date.

Sales:
LOAD Date#(SaleDate, 'YYYY-MM-DD') AS SaleDate, RepID, Amount
INLINE [
SaleDate, RepID, Amount
2026-02-10, R1, 100
2026-07-05, R1, 250
2026-07-06, R2, 90
];

RepHistory:
LOAD Date#(ValidFrom, 'YYYY-MM-DD') AS ValidFrom,
     Date#(ValidTo, 'YYYY-MM-DD') AS ValidTo,
     RepID, Territory
INLINE [
ValidFrom, ValidTo, RepID, Territory
2026-01-01, 2026-06-30, R1, North
2026-07-01, 2026-12-31, R1, South
2026-01-01, 2026-12-31, R2, North
];

Left Join (Sales)
IntervalMatch (SaleDate, RepID)
LOAD ValidFrom, ValidTo, RepID
RESIDENT RepHistory;

Left Join (Sales)
LOAD ValidFrom, ValidTo, RepID, Territory
RESIDENT RepHistory;

DROP TABLE RepHistory;
DROP FIELDS ValidFrom, ValidTo;
Enter fullscreen mode Exit fullscreen mode

Date# reads the text as a date, which gives each value a number behind it. That matters here, because IntervalMatch disregards an interval whose limits are not numeric. The intervals are closed, so a sale on 30 June still belongs to the first row.

The first join adds the matching ValidFrom and ValidTo to each sale, using SaleDate and RepID. The second join uses those fields to fetch Territory, and the two DROP statements remove what is no longer needed. The result is one Sales table in which rep R1 sold in North in February and in South in July. The IntervalMatch prefix reference covers both forms, with and without key fields.

If you leave the IntervalMatch table in the model as a separate table, it shares several fields with each of its neighbours, and the synthetic keys from the first script come back.

How do you prove the script loaded what you expected?

Count rows and count keys, and write both to the log. Validation is only 6% of the exam, but it is the habit that catches the mistakes from every other section. Add this after the Orders table from the mapping script.

LET vRows = NoOfRows('Orders');
LET vKeys = FieldValueCount('OrderID');
TRACE Orders: $(vRows) rows, $(vKeys) distinct OrderID values;
Enter fullscreen mode Exit fullscreen mode

NoOfRows returns the number of rows in a loaded table, and FieldValueCount returns the number of distinct values in a field. If OrderID is the primary key and the two numbers differ, a join has multiplied rows or the source holds duplicate keys. The Trace statement writes the line to the script progress window and to the script log.

Watch: a short overview of preparing for the QSDA exam

The video is from AnalyticsExam's channel and runs just under three minutes.

What should you do after the six scripts?

Change each script and predict the result before you reload. Add a fourth shared field to the first one. Put a duplicate customer in the mapping table. Move a sale to a date that no interval covers. Being able to say what the data model viewer will show before you open it is the skill the exam's scenario questions ask for.

Then practise reading those scenarios against the clock. AnalyticsExam publishes free QSDA sample questions that show the question style.

For the full length, 50 questions in 90 minutes works out to a little under two minutes each, and that pace needs practice as well.

The Qlik Sense Data Architect certification practice exam on the same site is timed and multiple choice, and it keeps a result history so you can track your progress from one attempt to the next.

Frequently asked questions

1. How many questions are on the Qlik Sense Data Architect exam?

The exam has 50 questions and lasts 90 minutes, and the passing score is 62%. Qlik notes that exam content is updated periodically and that the number and difficulty of questions may change.

2. Does the QSDA exam cover Qlik Cloud or client-managed Qlik Sense?

Both. Qlik describes the exam as platform-neutral, which means the content applies to client-managed Qlik Sense and to Qlik Cloud.

3. Which topic area carries the most weight on the QSDA exam?

Data Transformations carries the most at 38%, followed by Data Model Design at 28%. Identify Requirements is 20%, Data Connectivity is 8% and Validation is 6%.

4. Do I need to know SQL for the Qlik Sense Data Architect certification?

Qlik's recommended experience includes being familiar with SQL and relational databases. It also lists the ability to write Qlik Sense load scripts and validate data, and a basic understanding of extract, transform and load.

5. Is a synthetic key always a mistake?

No. Qlik's documentation says a synthetic key is sometimes correct, but that most times it is there because of an error in the script. Several synthetic keys, or one built on another, point to an incorrect data model.

Written by the team behind AnalyticsExam, an exam-prep site for analytics certifications. We are not affiliated with Qlik.

Top comments (0)