The most underused Qlik Sense feature: compare two independent selection contexts simultaneously in the same chart, without duplicating objects or hardcoding filters.
By default, a Qlik app has one selection state: the user clicks "Southeast" and every object reflects that selection. Alternate States break this constraint, enabling different objects to operate in independent, simultaneous selection contexts.
Consider this scenario: an analyst needs to compare the performance of two products with different filters applied to each, without creating a second app, without opening two tabs, without hardcoded Set Analysis values. Alternate States is Qlik's native answer to this problem.
Both states coexist in the same app at the same time. A single chart can display both values side by side. Users make selections in each state completely independently.
// Default state - same as {$}
Sum({$} Revenue)
// Alternate state by name
Sum({Scenario_B} Revenue)
// Alternate state + additional modifier
Sum({Scenario_B<Status={'Active'}>} Revenue)
// Difference between the two states
Sum({$} Revenue) - Sum({Scenario_B} Revenue)
// YoY % comparison between states
Num(
(Sum({$} Revenue) / Sum({Scenario_B} Revenue)) - 1,
'+#,##0.0%;-#,##0.0%;0.0%'
)
{StateName<Field={'Value'}>}. The state name replaces the default identifier ($ or 1). The modifier <> is optional - without it, the expression uses exactly the selections active in that state at runtime.
// Always ignores ALL selections
// Not interactive - never changes
Sum({1<Region={'South'}>} Revenue)
// Value is fixed regardless of
// what the user selects
// Uses selections of state Scenario_B
// The user can change those selections!
Sum({Scenario_B} Revenue)
// Value updates as user interacts
// with objects assigned to that state
Alternate States are not a feature for simple scenarios. They exist to solve comparative analysis problems that would otherwise require complex, fragile workarounds.
User selects January in State A and February in State B. A single bar chart shows both months side by side with the same dimensions, zero hardcoding.
Live benchmark between two regions chosen by the analyst. South vs North, Branch A vs Branch B - the choice belongs to the user, not the developer.
Current state vs simulated scenario. The default state reflects reality; the alternate state reflects a hypothesis with different filters, budget, or product mix.
Customers who bought Product A (State A) vs customers who bought Product B (State B). Which basket has a higher average ticket? More repeat purchases?
Same data with two different exchange rates. The CFO wants to see results in USD and BRL simultaneously with the same product and region filters.
Actual performance (default state) vs adjusted target (alternate state with modifiers). The variance is calculated directly in the expression.
States are created in the Qlik Sense interface and then referenced in any Set Analysis expression by the exact name you defined.
Click "Edit sheet" in the top right corner. In the sheet properties panel (not the object panel), find the Alternate States section.
Click "Add state". Define a name without spaces or special characters - this is the name you will use in Set Analysis. Ex: Scenario_B, Period_2.
Select the object (filter pane, chart, KPI). In the object properties panel, find State and select the created state. That object now operates in the new state.
Scenario_A and Scenario_B are generic but functional. Selected_Period and Benchmark_Region are better for production dashboards. Never use spaces or special characters - the name must be valid as an expression identifier.
Displays dimensions (Region, Product, Year). Object is assigned to the default state. Selections here affect all objects using {$}.
Displays the same dimensions. Object is assigned to state Scenario_B. Selections here only affect objects that reference this state in their expressions.
// The comparison chart stays in the default state
// It simply has two measures:
// Measure 1 - uses default state selections
Sum({$} Revenue)
// Label: "Revenue - Selection A"
// Measure 2 - uses Scenario_B state selections
Sum({Scenario_B} Revenue)
// Label: "Revenue - Selection B"
// Measure 3 - absolute difference between both states
Sum({$} Revenue) - Sum({Scenario_B} Revenue)
// Label: "Variance A vs B"
// Measure 4 - percentage variation
Num(
(Sum({$} Revenue) / Sum({Scenario_B} Revenue)) - 1,
'+#,##0.0%;-#,##0.0%;0.0%'
)
These battle-tested patterns combine Alternate States with the techniques from the previous articles: modifiers, P(), dollar-sign expansion, and dynamic periods.
// Setup: Two Region filter panes (State $ and State Region_B)
// User chooses any region in each filter independently
// Dynamic label showing which region is active per state
'Selected: ' & Concat({$} DISTINCT Region, ', ')
'Benchmark: ' & Concat({Region_B} DISTINCT Region, ', ')
// Revenue comparison
Sum({$} Revenue) // Region A
Sum({Region_B} Revenue) // Region B
// Variance
Num(
Sum({$} Revenue) / Sum({Region_B} Revenue) - 1,
'+#,##0.0%;-#,##0.0%;0.0%'
)
// Default state: customers who bought Product A
// State Cohort_B: customers who bought Product B
// Question: what is the cross-revenue between both groups?
// Customers exclusive to State A (bought A but not B)
Count(
{$<CustomerID =
P({$} CustomerID)
-
P({Cohort_B} CustomerID)
>}
DISTINCT CustomerID
)
// Customers in BOTH states (bought A and B)
Count(
{$<CustomerID =
P({$} CustomerID)
*
P({Cohort_B} CustomerID)
>}
DISTINCT CustomerID
)
// Revenue from overlapping customers
Sum(
{$<CustomerID =
P({$} CustomerID) * P({Cohort_B} CustomerID)
>}
Revenue
)
// State A: South Region, user's default period
// State Period_2: North Region, different period
// YTD for default selection
Sum({$<Year={$(=Max({1}Year))},
Month={"<=$(=Month(Today()))"}>} Revenue)
// YTD for alternate state - same period logic, different selections
Sum({Period_2<Year={$(=Max({1}Year))},
Month={"<=$(=Month(Today()))"}>} Revenue)
// Default state: actual performance
// State WhatIf: simulated scenario with different filters
// Actual
Sum({$} Revenue)
// Simulated: WhatIf state + Premium segment only
Sum({WhatIf<Segment={'Premium'}>} Revenue)
// Impact (absolute)
Sum({$} Revenue) - Sum({WhatIf} Revenue)
// Impact (percentage, signed)
Num(
(Sum({$} Revenue) - Sum({WhatIf} Revenue)) /
Abs(Sum({WhatIf} Revenue)),
'+#,##0.0%;-#,##0.0%;0.0%'
)
| Expression | Meaning | When to Use |
|---|---|---|
Sum({$} Revenue) | Default state (current selections) | Base reference measure |
Sum({1} Revenue) | All records, ignores selections | Fixed absolute total |
Sum({Scenario_B} Revenue) | Scenario_B state selections | A vs B comparison |
Sum({Scenario_B<Status={'Active'}>} Revenue) | State B + additional modifier | State B with extra condition |
Count({$} DISTINCT ID) - Count({Scenario_B} DISTINCT ID) | Count difference between states | Customer base growth/decline |
P({$} CustomerID) * P({Scenario_B} CustomerID) | Customer intersection between states | Basket / cohort analysis |
Sum(TOTAL {Scenario_B} Revenue) | State B total, ignores chart dimensions | Cross-state share % |
The name in Set Analysis must be identical to the name created in the interface, including upper/lowercase and underscores. {scenario_b} is different from {Scenario_B}.
Creating the state is not enough. Each object (filter pane, button) must be explicitly assigned to the correct state via the properties panel. A filter pane in the default state does not feed an alternate state.
The comparison chart must be in the default state ($) to show both measures. If the chart itself is assigned to a specific state, it only reflects that state's selections.
{Scenario_B<Field={'Val'}>} uses State B selections AND adds the modifier. {$<Field={'Val'}>} uses default state with modifier. These are different contexts.
Comparison_Period is better than State2ClearAll() for that stateConcat({StateName} DISTINCT Field, ', ') in text objects to show users what is selected in each state