Expressions de table communes
Les expressions de table communes représentent des sous-requêtes nommées. Elles peuvent être référencées par leur nom partout dans une requêteSELECT où une expression de table est autorisée.
Les sous-requêtes nommées peuvent être référencées par leur nom dans la portée de la requête courante ou dans les portées des sous-requêtes enfants.
Chaque référence à une expression de table commune dans une requête SELECT est toujours remplacée par la sous-requête de sa définition si la CTE n’est pas explicitement définie comme matérialisée (voir Expressions de table communes matérialisées).
La récursivité est évitée en masquant la CTE courante du processus de résolution des identifiants.
Veuillez noter que les CTE ne garantissent pas les mêmes résultats partout où elles sont appelées, car la requête est réexécutée à chaque utilisation.
Syntaxe
Exemple
Voici un exemple de cas où une sous-requête est réexécutée :1000000
Cependant, comme nous faisons référence deux fois à cte_numbers, des nombres aléatoires sont générés à chaque fois et nous obtenons donc des résultats aléatoires différents : 280501, 392454, 261636, 196227, etc.
Expressions de table communes matérialisées
Par défaut, ClickHouse intègre la sous-requête d’une CTE à chaque référence, et la réexécute donc à chaque fois. L’ajout du mot-cléMATERIALIZED indique à ClickHouse d’exécuter la sous-requête de la CTE exactement une fois, de stocker les résultats dans une table temporaire, puis d’utiliser cette table pour toutes les références.
Cela est particulièrement utile lorsque la même CTE est référencée plusieurs fois dans une requête (par exemple, dans des auto-jointures ou plusieurs sous-requêtes IN), car le calcul sous-jacent n’est effectué qu’une seule fois.
Les CTE matérialisées sont une fonctionnalité expérimentale.
Elles nécessitent que le paramètre
enable_materialized_cte soit activé.
Si le paramètre est désactivé, le mot-clé MATERIALIZED est ignoré : la CTE est intégrée à chaque référence comme une CTE ordinaire, et un avertissement est journalisé.Syntaxe
Quand utiliser
Les CTE matérialisées sont particulièrement utiles dans les cas suivants :- La même CTE est référencée plus d’une fois dans une requête.
Sans
MATERIALIZED, chaque référence réexécute la sous-requête de manière indépendante. - La CTE contient des fonctions non déterministes comme
generateRandom. La matérialisation garantit que toutes les références voient les mêmes données. - La CTE implique des calculs coûteux (agrégations, jointures, lecture de grands volumes de données) qu’il ne faut pas répéter.
Exemples
Exemple 1 : Auto-jointure sur une CTE matérialisée SansMATERIALIZED, les deux côtés de la jointure exécuteraient la sous-requête indépendamment.
Avec MATERIALIZED, la table n’est parcourue qu’une seule fois et les deux côtés de la jointure lisent dans la même table temporaire.
generateRandom produisent des résultats différents à chaque référence.
La matérialisation de la CTE garantit la cohérence :
1000000.
Exemple 3 : Chaînage de CTE matérialisées
Les CTE matérialisées peuvent faire référence à d’autres CTE matérialisées.
ClickHouse résout les dépendances et les matérialise dans le bon ordre :
Restrictions
- Paramètre expérimental requis : le paramètre
enable_materialized_ctedoit être activé. S’il est désactivé, le mot-cléMATERIALIZEDest ignoré : la CTE est intégrée à chaque référence comme une CTE ordinaire, et un avertissement est journalisé. - Non pris en charge avec
RECURSIVE: la combinaison des mots-clésMATERIALIZEDetRECURSIVEn’est pas autorisée et entraîne une exceptionUNSUPPORTED_METHOD. - Les CTE corrélées sont interdites : une CTE matérialisée ne peut pas référencer des colonnes provenant de portées de requête englobantes.
Expressions scalaires communes
ClickHouse vous permet de déclarer des alias pour des expressions scalaires arbitraires dans la clauseWITH.
Les expressions scalaires communes peuvent être référencées n’importe où dans la requête.
Si une expression scalaire commune fait référence à autre chose qu’un littéral constant, elle peut entraîner la présence de variables libres.
ClickHouse résout chaque identifiant dans la portée la plus proche possible, ce qui signifie que des variables libres peuvent faire référence à des entités inattendues en cas de conflit de noms, ou conduire à une sous-requête corrélée.
Il est recommandé de définir une CSE sous forme de fonction lambda, en liant tous les identifiants utilisés afin d’obtenir un comportement plus prévisible lors de la résolution des identifiants d’expression.
Syntaxe
Exemples
Exemple 1 : Utiliser une expression constante comme “variable”extension n’est pas liée dans le corps de la fonction lambda gen_name.
Bien que extension soit définie comme '.txt' en tant qu’expression scalaire commune dans la portée de définition et d’utilisation de generated_names, elle est résolue comme une colonne de la table extension_list, car elle est disponible dans la sous-requête generated_names.
Requêtes récursives
Le modificateurRECURSIVE, facultatif, permet à une requête WITH de faire référence à son propre résultat. Exemple :
Exemple : Additionner les entiers de 1 à 100
Les CTE récursifs s’appuient sur l’analyseur de requêtes, introduit dans la version
24.3, qui constitue le comportement par défaut depuis cette version et est obligatoire depuis la version 26.9. Sur une version plus ancienne où l’analyseur est encore désactivé sur l’instance, le rôle ou le profil, un CTE récursif lève une exception (UNKNOWN_TABLE) ou (UNSUPPORTED_METHOD) ; activez alors le paramètre enable_analyzer, ou effectuez une mise à niveau.WITH est toujours la suivante : un terme non récursif, puis UNION ALL, puis un terme récursif, seul ce dernier pouvant contenir une référence à la propre sortie de la requête. Une requête CTE récursive s’exécute comme suit :
- Évaluez le terme non récursif. Placez le résultat de cette requête dans une table de travail temporaire.
- Tant que la table de travail n’est pas vide, répétez ces étapes :
- Évaluez le terme récursif en remplaçant l’auto-référence récursive par le contenu actuel de la table de travail. Placez le résultat de cette requête dans une table intermédiaire temporaire.
- Remplacez le contenu de la table de travail par celui de la table intermédiaire, puis videz la table intermédiaire.
Ordre de parcours
Pour établir un parcours en profondeur, nous calculons pour chaque ligne de résultat un tableau des lignes déjà visitées : Exemple : Parcours d’arbre en profondeurDétection des cycles
Commençons par créer la table du graphe :Maximum recursive CTE evaluation depth :
Requêtes infinies
Il est également possible d’utiliser des requêtes CTE récursives infinies siLIMIT est utilisé dans la requête externe :
Exemple : Requête CTE récursive infinie
Virgule finale
Une virgule est autorisée après le dernier élément de la clauseWITH :