Tutorial - Chart Expressions
Tutorial - Chart Expressions
Qlik Sense®
May 2024
Copyright © 1993-2024 QlikTech International AB. All rights reserved.
HELP.QLIK.COM
© 2024 QlikTech International AB. All rights reserved. All company and/or product names may be
trade names, trademarks and/or registered trademarks of the respective owners with which they
are associated.
Contents
Chart expressions are mostly used in measures. You can also build visualizations that are more
dynamic and powerful by using expressions for titles, subtitles, footnotes, and even dimensions.
You will need access to the data load editor and should be allowed to load data in Qlik Sense
Enterprise on Windows.
Visualizations can have titles, subtitles, footnotes, and other elements to help convey information.
The elements that make up a visualization can be simple. For example: a dimension consisting of a
fieldrepresenting data, and a title consisting of text.
Measures are calculations based on fields. For example: Sum(Cost) means that all the values of the
field Cost are aggregated using the function Sum. In other words, Sum(Cost) is an expression.
All measures are expressions. The difference between measures and expressions is that
expressions have no name or descriptive data.
You can build visualizations that are more dynamic and powerful by using expressions for
dimensions, titles, subtitles, and footnotes. This means, for example, that instead of a static text,
the title of a visualization can be generated from an expression whose result changes depending on
your selections.
An expression cannot be saved directly as a master item. However, master measures and master
dimensions can contain expressions. If an expression is used in a measure or dimension which is
then saved as a master item, the expression in the measure or dimension is preserved.
You can use the expression editor to create and change expressions in Qlik Sense.
Let us calculate the total sales that each manager has made, as well at the total sales of all
managers.
Inside the app on the Which Aggregations? sheet you will find two tables, a table titled Sum(), Max
(), Min(), and a table titled Count(). We will use each table to create aggregation functions.
Do the following:
You can see the sales that each manager has made, as well as the total sales of all managers.
As a best practice, make sure that your data is formatted appropriately. In this case, set
the Number formatting to Money, and the Format pattern to $ #,##0;-$ #,##0.
Do the following:
You can see that the highest sales earnings for each manager, as well as the highest total number.
Do the following:
Table showing total sales, highest sale, and lowest sale per Manager
You can see the lowest sales earnings for each manager, as well as the lowest total number.
In our data, each manager is responsible for a number of sales representatives (Sales Rep Name).
Let us calculate the number of sales representatives.
Do the following:
You can see that the total number of sales representatives is 64.
Do the following:
6. Click Apply.
Table showing Sales Representatives, total number of Sales Representatives, Manager responsible for each
Sales Representative, incorrect total number of Managers, and correct total number of Managers.
You can see that the total number of managers on the column using Count(Manager) as an
expression was calculated as 64. That is not correct. The total number of managers is correctly
calculated as 18 using the Count(distinct Manager) expression. Each manager is only counted once,
regardless of how many times their name appears on the list.
4 Nested aggregations
Any field name in a chart expression must be enclosed by exactly one aggregation
function. If you need to nest aggregations, you can use Aggr() to add a second
aggregation level. Aggr() contains an aggregation function as an argument.
All three numbers may still represent all data, despite the difference in magnitude. The numbers are
just different aggregation levels.
Aggregation functions use the values from many records as input and collapse these into one single
value that can be seen as a summary of all records. There is one restriction: you cannot use an
aggregation function inside another aggregation function. You usually need every field reference to
be wrapped in exactly one aggregation function.
The solution to this comes in the form of the Aggr() function. Contrary to its name it is not an
aggregation function. It is a "many-to-many" function, like a matrix in mathematics. It converts a
table with N records to a table with M records. It returns an array of values. It could also be
regarded as a virtual straight table with one measure and one or several dimensions.
Use the Aggr() function in calculated dimensions if you want to create nested chart
aggregations on multiple levels.
When it is used, the Aggr() statement produces a virtual table, with one expression grouped by one
or more dimensions. The result of this virtual table can then be aggregated further by an outer
aggregation function.
We want to see our overall metrics at the regional level, but also show two more complex
expressions:
l Largest average order value by manager within each region.
l Manager responsible for that largest average order value.
We can easily calculate the average order value for each region using a standard expression Sum
(Sales)/Count([Order Number]).
Inside the app, on the Nested Aggregations sheet you will find a table titled Aggr() function.
Do the following:
As a best practice, make sure that your data is formatted appropriately. In this case, in
each column we will change the Label to represent the calculation. In columns with
monetary values we will change the Number formatting to Money, and the Format
pattern to $ #,##0;-$ #,##0.
Our goal is to retrieve the largest average order value for each region. We have to use Aggr() to tell
Qlik Sense that we want to grab the average order value for each region, per manager, and then
display the largest of those. To get the average order value for each region, per manager, we will
have to include these dimensions in our Aggr() statement:
This expression causes Qlik Sense to produce a virtual table that looks like this:
Virtual table of Aggr() function showing average order value for each region, per manager.
When Qlik Sense calculates the individual average order values for each region, per manager, we
will need to find the largest of these values. We do this by wrapping the Aggr() function with Max():
Do the following:
Table showing region, average order value, and largest average order value for each region, per manager.
You can see the largest average order value for all managers at the region level. This is the first of
our two complex expressions! The next requirement is to have the name of the manager
responsible for these large average order values displayed next to the values themselves.
To do this, we will use the same Aggr() function as before, but this time together with the
FirstSortedValue() function. The FirstSortedValue() function tells Qlik Sense to provide us with
the manager, for the specific dimension specified in the second portion of the function:
There is one small, but very important, part of the expression: there is a minus symbol
before the Aggr() expression. Within a FirstSortedValue() function, you can specify the
sort order of the array of data. In this case, the minus symbol tells Qlik Sense to sort from
largest to smallest.
Do the following:
Table showing region, average order value, largest average order value for each region, and manager
responsible for that order value.
Two tables, one showing that Max(Invoice Date) is a single value, and one showing that Invoice Date is an
array of values.
You must enclose the field Invoice Date in an aggregation function to make it collapse into a single
value.
If you do not use an aggregation function on your expression, Qlik Sense will use the Only()
function by default. If the field reference returns several values, Qlik Sense will interpret it as NULL.
Inside the app on the Naked field referencessheet you will find a table titled Using If() on Invoice
dates.
Do the following:
This expression tests if the Invoice Date is before the reference date 2/18/2013 and returns 'Before'
if it is. If the date is after or equal to the reference date 2/18/2013, 'After' is returned. The reference
date is expressed as the integer number 41323.
It should evaluate invoice dates after the reference date, return 'After' or else return 'Before'.
However, Invoice Date is a naked field reference, it does not have an aggregation function, and as
such is an array with several values and will evaluate to NULL. In the previous example, there was
only one Invoice Date per Date value in our table, so the expression calculated correctly.
Let's see how a similar expression calculates under a different dimensional value, and how to solve
the naked field reference issue:
This time the function sums the sales after the reference date.
Inside the app, on the Naked field references sheet you will find a table titled Sum(Amount).
Do the following:
Table showing year, sum of sales for each year, and the results of the expression using the If() function.
Keep the Label intact on the measures to show the differences between each
expression. In columns with monetary values, change the Number formatting to Money,
and the Format pattern to $ #,##0;-$ #,##0.
For each year there is an array of invoice dates that come after the reference date. Since our
expression lacks an aggregation function it evaluates to NULL. A correct expression should use an
aggregation function such as Min() or Max() in the first parameter of the If() function:
Do the following:
Table showing year, sum of sales for each year, and the results of the different expressions using the If()
function.
Alternatively, the If() function can be put inside the Sum() function:
Do the following:
Table showing year, sum of sales for each year, and the results of the different expressions using the If()
function.
In the second to last expression, the If() function was evaluated once per dimensional value. In the
last expression, it is evaluated once per row in the raw data. The difference in how the function is
evaluated causes the results to be different, but both return an answer. The first expression simply
evaluates to NULL. The picture above shows the difference between the expressions, using
2/18/2013 as the reference date.
If there is a one-to-one relationship between the chart dimensionand the parameter, the Only()
function returns the only possible value. If there are several values, it returns NULL. For example,
searching for the only product where the unit price =12 will return NULL if more than one product
has a unit price of 12.
The following images show the difference between one-to-one and one-to-many relationships:
The Only() function is an aggregation function. It uses many records as input and returns one value
only, similarly to Sum() or Count(). Qlik Sense uses aggregations in virtually all its calculations. The
expression in a chart, in a sort expression, in a text box, in an advanced search, and in a calculated
label are all aggregations and cannot be calculated without involving an aggregation function.
But what if a user enters an expression that lacks an explicit aggregation function? For example, if
the sort expression is set to Date? Or if there is an advanced search for customers who have
bought beer and wine products using the expression =[Product Type]='Beer and Wine'?
This is where the Only() function affects the calculation. If there is no explicit aggregation function
in the expression, Qlik Sense uses the Only() function implicitly. In the above cases, Only(Date) is
used as sort expression and Only([Product Type])='Beer and Wine' is used as the search
criterion.
Sometimes the new expression returns a result that the user does not expect. Both of the examples
above will work when there is only one possible value of Date or Product Type, but neither of them
will work for cases when there is more than one value.
Inside the app on the Importance of Only()sheet you will find a filter pane with Invoice Date as the
dimension.
Do the following:
1. Create a KPI.
2. Click Add measure. Click on the symbol.
The expression editor opens.
3. Enter the following: Month([Invoice Date])
4. Create three more KPIs with measures: Month(Only([Invoice Date])), Month(Max([Invoice
Date])), and Only(Month([Invoice Date])).
5. Click Apply.
Four KPIs and a filter pane showing three different but similar expressions.
In each KPI the Number formatting has been set to Measure expression.
When you have a naked field reference, the Only() function is inserted at the lowest level. That
means that the first two KPIs, Month([Invoice Date]) and Month(Only([Invoice Date])), will be
interpreted the same and will always give the same result.
As you can see three of the four KPIs return NULL. The third KPI, Month(Max([Invoice Date])),
already returns a value, even though no selection has been made.
When you write expressions you should always ask yourself which aggregation you want to use, or
which value you want to use if there are several values. If you want to use NULL to represent
several values, you can leave the expression as is. For numbers, you probably want to use Sum(),
Avg(), Min(), or Max() instead. For strings you may want to use Only() or MinString().
Do the following:
When a single selection is made, all of the KPIs return the correct answer. Even if the expression
contains a naked field reference, such as the expression in Month([Invoice Date]), the fact that we
have made a unique selection allows it to return the proper value.
Do the following:
The KPI results change when two selections are made with both dates in the month of January.
The first two KPIs return NULL, and the other two KPIs return the proper value of January.
Specifically, the fourth KPI returns a correct answer because both the date selections we made are
for dates in January.
Do the following:
1. In the filter pane, select an additional date, in a month other than January.
2. Confirm the selection by clicking .
The KPI results change when multiple selections are made with dates in different months.
When multiple selections are made, using dates in different months, only the third KPI returns a
value. It returns the value of the largest month from the selection made, according to the
expression Month(Max([Invoice Date])). Since Only() is inserted automatically in expressions with
naked field references you cannot always assume that the lowest level will be appropriate for your
expression. The placement of Only() is important.
Inside the app, on the Examples from real life sheet, you will find a table titled Margin.
Do the following:
Table showing sum of sales, and sum of cost per month, as well as calculated margin per month in both
amount and percentage forms
As a best practice, make sure that your data is formatted appropriately. In this case, in
each column we will change the Label to represent the calculation. In columns with
monetary values we will change the Number formatting to Money, and the Format
pattern to $ #,##0;-$ #,##0. Set the Number formatting of the margin percentage to
Number, and the Formatting to Simple and 12%.
You can see the calculated margin for each month based on the sales and the cost. You can also
see what percentage of the sales makes up our margin.
In the app data, we already have data for the monthly margin. This is a good opportunity to make a
comparison between our original data and our calculation.
Do the following:
The margin table with additional columns for monthly margin coming from the data set, and its difference to
the calculated margin.
Some values in the calculated margin column differ from the values from the margin column coming
directly from our data. The margin discrepancy column clearly shows that this takes place in a
months during 2014. The difference between the calculated margin and the margin coming from the
data set is small, but the fact that it takes place in a specific year creates some questions. What
changed during that year? Looking into the data and asking the right questions might prove to be
important for your business.
always the same as the invoice date, as it is automatically created by the invoicing system used by
the company. The largest promised delivery date is the date when a delivery was agreed to be
made between the company and the client.
On the Examples from real life sheet you will find a table titled Invoicing delays.
Do the following:
Table showing promised delivery date and invoice date for each invoice
As a best practice, make sure that your data is formatted appropriately. In columns that
show dates, set the Number formatting to Date, and set the Formatting to Simple and
17 Feb 2014.
You can see that the invoice date and the promised delivery date are not always the same. When
there are two promised delivery dates we need to use the largest one for our calculation.
Let us calculate the difference between the invoice date and the promised delivery date. We will
use the following expression:
Max([Promised Delivery Date])-[Invoice Date]
Do the following:
Table showing promised delivery date and invoice date for each invoice, as well as the number of days from
invoicing to promised delivery
Sort the table based on the last column, named Days from invoicing to delivery.
There is a range of differences between the dates. Negative values indicate that the invoice was
delayed. Positive numbers indicate that the promised delivery was done after the invoice was
created.
Let us calculate the number of invoices that were made after the promised delivery date.
Do the following:
The invoicing delays table with additional column showing the number of delayed invoices.
The last column makes more sense as a KPI as a percentage of the total number of invoices.
Do the following:
1. Create a KPI.
2. Click Add measure. Click on the symbol.
The expression editor opens.
3. Enter the following: Count(Distinct If(Aggr(Max([Promised Delivery Date])<[Invoice Date],
[Invoice Number]),[Invoice Number]))/Count([Invoice Number])
4. Click Apply.
Do the following: