· Par Équipe HeyData

Série : Fonctions et mots-clés méconnus de Qlik Sense : une série · article 10 sur 13

Dual() et la double nature des valeurs dans Qlik Sense

Pourquoi un champ de mois se trie-t-il de janvier à décembre, et non d’avril à septembre ? Pourquoi des codes comptables 001 et 1 fusionnent-ils parfois en un seul ? Les deux réponses tiennent à une particularité du moteur Qlik : une valeur de champ peut avoir deux natures à la fois, un texte et un nombre. La fonction Dual() permet de construire ces valeurs soi-même.

Cet article fait partie de notre série sur les fonctions et mots-clés méconnus de Qlik Sense. Il s’appuie sur l’aide Qlik ; les liens sont en fin d’article.

Un texte et un nombre

Une date est l’exemple le plus courant : 2026-03-15 s’affiche en texte, mais vaut un nombre (le numéro de série du jour), ce qui permet de la trier, de la comparer et de lui soustraire une autre date. Les fonctions d’interprétation comme Date#() ou Num#() produisent de telles valeurs. Dual(texte, nombre) en fabrique une à partir de deux expressions.

Le résultat de Dual('Haute', 3) décomposé en deux cases : le texte 'Haute', utilisé pour l’affichage, les volets de filtre et la comparaison à une chaîne ; le nombre 3, utilisé pour le tri, les calculs et la comparaison à un nombre. À droite, trois priorités triées : en ordre alphabétique Basse, Haute, Moyenne ; en ordre numérique Basse (1), Moyenne (2), Haute (3).

Le texte s’affiche, le nombre trie et calcule.

Le moteur choisit la nature qui convient au contexte : le texte pour l’affichage, le nombre pour le tri numérique et les calculs. Priority = 'Haute' compare le texte, Priority >= 2 compare le nombre.

Trier sans table de tri

Le cas d’usage classique : des libellés qui doivent suivre un ordre métier.

Tickets:
LOAD TicketID,
     Dual(Pick(PriorityCode, 'Basse', 'Moyenne', 'Haute'), PriorityCode) as Priority
INLINE [
TicketID, PriorityCode
T1, 3
T2, 1
T3, 2
];

Dans un graphique, Priority trié numériquement donne Basse, Moyenne, Haute. L’aide Qlik donne deux autres exemples utiles, à adapter :

Dual('T' & Ceil(Month(Date) / 3), Ceil(Month(Date) / 3))   as Trimestre,
Dual(WeekYear(Date) & '-S' & Week(Date), WeekStart(Date))   as Semaine

Le trimestre s’affiche T1 à T4 et se trie de 1 à 4. La semaine s’affiche 2026-S12 et se trie par la date de son premier jour, ce qui règle le passage d’une année à l’autre.

Un indicateur qui se somme

Dual() sert aussi pour les indicateurs : Dual('Oui', 1) et Dual('Non', 0) s’affichent en clair dans un volet de filtre, et Sum(HasOrder) compte directement les clients qui ont commandé. Notre article sur NULL et l’absence de valeur en donne un exemple avec Exists().

Le piège : la première représentation l’emporte

Un champ ne garde qu’un seul texte par valeur numérique. Si deux valeurs ont le même nombre mais des textes différents, elles partagent toutes le premier texte rencontré au chargement. L’aide Qlik le précise pour Dual(), mais la règle vaut pour toute valeur interprétée comme un nombre.

À gauche, la source Accounts chargée dans l’ordre : 001, puis 1, puis 002. Au milieu, un LOAD Code ordinaire : le champ ne compte que deux valeurs, 001 et 002, car 001 et 1 valent tous deux 1 et partagent le texte chargé en premier ; la ligne 001 est surlignée. À droite, un LOAD Text(Code) garde trois valeurs distinctes : 001, 1 et 002.

‘001’ arrive en premier : ‘1’ s’affichera aussi ‘001’.

Le cas réel le plus fréquent concerne les codes : comptes, articles, codes postaux. 001 et 1 sont interprétés comme le nombre 1 et fusionnent en une seule valeur. Pour un identifiant, la règle est simple : forcez le texte au chargement.

Accounts:
LOAD Text(Code) as Code, Label
FROM [lib://Data/Accounts.csv] (txt, utf8, embedded labels, delimiter is ';');

À l’inverse, la règle se met à profit : charger une petite table de libellés avant les faits fixe l’affichage des valeurs. C’est ce que recommande l’aide pour contrôler le texte d’un Dual().

À retenir

  • Deux natures par valeur. Un texte pour l’affichage et la comparaison à une chaîne, un nombre pour le tri et les calculs.
  • Dual() trie les libellés. Priorités, trimestres, semaines : l’ordre métier sans table de tri.
  • Un indicateur Dual se somme. Dual('Oui', 1) s’affiche en clair et se compte avec Sum().
  • Le premier texte l’emporte. Deux valeurs de même nombre partagent le texte chargé en premier.
  • Text() pour les codes. Un identifiant à zéros initiaux doit être chargé en texte.

Essayer dans Qlik Sense

Ce script reprend les exemples de l’article avec les données des schémas, chargées en INLINE : il ne dépend d’aucun fichier ni d’aucune base. Collez-le dans l’éditeur de chargement de données d’une application vide, choisissez l’exemple avec la variable vExemple, puis rechargez.

// Dual() dans Qlik Sense : script d'essai (HeyData)
// Collez-le dans l'éditeur de chargement de données d'une application vide, choisissez
// l'exemple, rechargez, puis affichez les champs dans un volet de filtre ou une table.
SET vExemple = 1;   // 1 à 3

IF $(vExemple) = 1 THEN
    // Exemple 1 : des priorités triées dans l'ordre métier (premier schéma)
    Tickets:
    LOAD TicketID,
         Dual(Pick(PriorityCode, 'Basse', 'Moyenne', 'Haute'), PriorityCode) as Priority,
         Date(Date#(OpenDate, 'YYYY-MM-DD')) as OpenDate,
         Dual('T' & Ceil(Month(Date#(OpenDate, 'YYYY-MM-DD')) / 3),
              Ceil(Month(Date#(OpenDate, 'YYYY-MM-DD')) / 3)) as Trimestre
    INLINE [
    TicketID, PriorityCode, OpenDate
    T1, 3, 2026-02-10
    T2, 1, 2026-05-04
    T3, 2, 2026-11-20
    ];
    // Volet de filtre Priority, tri numérique : Basse, Moyenne, Haute.
END IF

IF $(vExemple) = 2 THEN
    // Exemple 2 : la première représentation l'emporte (deuxième schéma)
    AccountsNumeric:
    LOAD Code as CodeNumeric INLINE [
    Code
    001
    1
    002
    ];

    AccountsText:
    LOAD Text(Code) as CodeText INLINE [
    Code
    001
    1
    002
    ];
    // CodeNumeric : 2 valeurs, 001 et 002. CodeText : 3 valeurs, 001, 1 et 002.
END IF

IF $(vExemple) = 3 THEN
    // Exemple 3 : un indicateur Dual qui se somme
    Customers:
    LOAD CustomerID,
         If(Orders > 0, Dual('Oui', 1), Dual('Non', 0)) as HasOrder
    INLINE [
    CustomerID, Orders
    C1, 3
    C2, 0
    C3, 1
    ];
    // Volet de filtre HasOrder : Oui, Non. Mesure Sum(HasOrder) : 2.
END IF

Sources

Le texte et les exemples sont de HeyData. Cet article fait partie de notre série sur les fonctions et mots-clés méconnus de Qlik Sense : découvrir la série.