Skip to main content
ClickHouse peut analyser un sous-ensemble du Kusto Query Language à la place de SQL. Ce dialecte est expérimental et désactivé par défaut :
SET dialect = 'clickhouse' permet de revenir au dialecte précédent. SET est la seule instruction SQL reconnue lorsque le dialecte KQL est actif, afin qu’une session puisse toujours le quitter.

Éléments pris en charge

Il s’agit volontairement d’un sous-ensemble restreint. Une construction KQL est soit traduite conformément à la sémantique documentée par Kusto, soit rejetée explicitement avec une erreur d’analyse — aucune approximation n’est effectuée silencieusement. Si une requête est analysée, son résultat doit correspondre à celui de Kusto. Sources : un nom de table, print, datatable, range, un pipeline entre parenthèses et union. Un range part d’un nombre avec un pas numérique, d’une date-heure avec un pas correspondant à une durée, ou d’une durée avec un pas correspondant à une durée. Opérateurs : where / filter, extend, project, project-away, project-keep, project-rename, summarize, sort by / order by, take / limit, top, distinct, count, mv-expand, join, union, as, render. Opérateurs scalaires : ==, !=, <, <=, >, >=, =~, !~, in, in~, between, contains, startswith, endswith, has, hasprefix, hassuffix, leurs variantes _cs (sensibles à la casse) et ! (négatives), has_any, has_all et matches regex. in et !in acceptent également une expression tabulaire dont la première colonne fournit les valeurs (x in (T | project key)); in~ n’accepte qu’une liste. Un nom seul dans in (...) qu’aucun let ne lie est interprété comme une colonne, car l’analyseur ne dispose d’aucun schéma permettant de distinguer une colonne d’une table ; liez la table avec let, qualifiez-la (db.table) ou ajoutez un pipe pour obtenir la forme tabulaire. Instructions : let, qui lie un scalaire, une expression tabulaire complète ou une fonction :
Les fonctions acceptent des paramètres scalaires avec des valeurs par défaut littérales facultatives, ainsi que des paramètres tabulaires déclarés T: (*) ou T: (col: type, ...), qui doivent figurer en premier. Un paramètre tabulaire qui nomme ses colonnes n’expose au corps que les colonnes correspondantes de l’argument, de sorte qu’un corps qui lit une colonne non déclarée est rejeté, même lorsque l’argument concret la contient ; T: (*) transmet l’argument tel quel. Les types déclarés sont vérifiés à la frontière de l’appel : un argument (ou une colonne déclarée d’un argument tabulaire) dont le type n’appartient pas au type KQL déclaré est rejeté, une conversion sans perte telle que de long vers real est appliquée, et une valeur qui ne correspond pas au type déclaré — par exemple, un dépassement de capacité de int — produit une erreur plutôt qu’une troncature silencieuse. Les arguments peuvent être transmis par nom dans n’importe quel ordre (f(c = 7, a = 12)). Un corps se compose d’un nombre quelconque d’instructions let suivies d’ une expression, et peut accéder aux liaisons qui l’englobent. Une fonction dont le corps est un pipeline renvoie une table plutôt qu’une valeur ; elle est donc rejetée là où une expression est attendue - dans extend, where ou print. Une fonction sans paramètre peut être appelée avec ou sans parenthèses. view () est accepté et, puisque rien ici ne résout les caractères génériques de union *, a la même signification que (). La récursion est rejetée, comme dans Kusto. Un let ne crée une liaison que pour l’instruction qui le suit, car une instruction KQL correspond à une requête ClickHouse — ce qui empêche également une liaison de fuiter dans une requête concurrente. Un nom dont deux instructions ont besoin doit être lié deux fois. Littéraux : chaînes (y compris les chaînes verbatim @'...'), nombres, datetime(...), guid(...), durées telles que 1d / 2.5h / 500ms, et tableaux dynamic([...]). Environ 130 fonctions scalaires et d’agrégation sont traduites. Comme dans Kusto, les fonctions d’agrégation ne peuvent être appelées que dans la liste d’agrégation de summarize ; print count() est rejeté plutôt que transmis à la fonction d’agrégation ClickHouse du même nom. Les fonctions ClickHouse sont également accessibles. Un nom que le registre KQL ne connaît pas est transmis à ClickHouse avec l’orthographe utilisée, afin qu’une requête puisse utiliser tout ce que le serveur propose :
L’exception concerne les noms que Kusto définit lui-même mais que ce dialecte n’implémente pas : ils sont rejetés plutôt que transmis tels quels, afin qu’un nom Kusto ne puisse jamais désigner discrètement autre chose. range en est l’exemple le plus clair — range(1, 3, 1) donne [1, 2, 3] dans Kusto et [1, 2] dans ClickHouse ; son utilisation en KQL génère donc une erreur plutôt qu’un résultat incorrect.

Couverture par rapport à la référence Kusto

Évaluée par rapport aux propres index de Microsoft (opérateurs tabulaires, fonctions scalaires, fonctions d’agrégation) : Les opérateurs pris en charge sont ceux enseignés dans le tutoriel Learn common operators de Microsoft, ainsi que datatable, range, print, union et join — suffisamment pour les types de requêtes que ce tutoriel et la référence rapide KQL permettent de construire progressivement.

Ce qui n’est pas pris en charge

Les éléments suivants sont rejetés avec une erreur d’analyse plutôt que traduits incorrectement :
  • Opérateurs : search, parse, mv-apply, lookup, evaluate, invoke, facet, top-nested, make-series, sample, serialize, partition, range utilisé comme opérateur.
  • Fonctions : la famille series_*, bag_* / pack_*, parse_url, parse_csv, parse_json, todynamic, toscalar, format_timespan, format_datetime, extract_all, range, la famille percentiles* et les fonctions de fenêtre row_*. (format_datetime et extract_all sont rejetées plutôt qu’approximées : les spécificateurs de format yyyy-MM-dd de Kusto ne sont pas ceux de ClickHouse, et extract_all de Kusto renvoie un tableau par groupe de capture.)
  • Noms Kusto qui entrent en conflit avec une fonction ClickHouse de sens différent : range (indiqué ci-dessus), repeat, replace, translate et materialize. Les laisser passer tels quels calculerait silencieusement autre chose — repeat(1, 3) en Kusto produit le tableau [1, 1, 1], tandis que repeat de ClickHouse répète une chaîne — ils sont donc tous rejetés par leur nom.
  • Les fonctions géospatiales qui acceptent ou renvoient du GeoJSON — toutes les fonctions geo_*_to_central_point, ainsi que tout ce qui opère sur des polygones et des lignes. Les fonctions de points, de geohash et H3 qui utilisent directement longitude/latitude sont prises en charge. geo_point_to_s2cell ne l’est pas : ClickHouse ne propose pas de forme de jeton S2.
  • Les objets dynamic (dynamic({"a": 1})), l’accès aux membres (x.y) et la recherche par clé (x['k']). Seuls les tableaux dynamic sont mappés vers Array de ClickHouse. dynamic en tant que type déclaré — dans un schéma datatable, un typeof(...) ou un paramètre de fonction — est également rejeté : l’annotation ne contient aucun type d’élément, il n’existe donc aucune correspondance fidèle.
  • Références inter-clusters et inter-bases de données telles que cluster(...) et database(...).
  • Indications pour les requêtes et les join (hint.strategy, hint.shufflekey, …).
  • Options d’opérateur : mv-expand ... to typeof(T) / limit N / bagexpansion, indications pour summarize, union kind= / withsource= / isfuzzy=, join hint.*.
  • Motifs génériques de colonnes dans project-away et project-keep (project-away Tmp*) : leur développement nécessite le schéma, qui n’est pas visible lors de l’analyse. Énumérez explicitement les colonnes.
  • L’intégralité du mécanisme de plug-ins evaluate, ainsi que bag_unpack, pivot, narrow, python, R et les autres.
  • Instructions d’application : alias database, declare pattern, declare query_parameters, restrict access to.
  • Littéraux de chaîne obfusqués (h"...") et littéraux multilignes (triple accent grave).

Comportements à connaître

  • Les durées sont des valeurs Interval. 1d devient toIntervalNanosecond(86400000000000). Définissez interval_output_format = 'kusto' pour les afficher au format Kusto (1.00:00:00) plutôt que sous forme de nombre.
  • La division suit les règles de Kusto : 7 / 2 donne 3, car les deux opérandes sont des entiers, et une durée divisée par une durée donne leur rapport réel (15ms / 10ms donne 1.5). Ce comportement est implémenté par kqlDivide, qui se base sur les types d’arguments.
  • La soustraction de deux valeurs date-heure donne un nombre de secondes, alors que Kusto renvoie une durée. L’ajout ou la soustraction d’une durée fonctionne comme prévu.
  • sort trie par défaut par ordre décroissant, contrairement à SQL, et place les valeurs nulles à l’extrémité inférieure.
  • project-rename déplace la colonne renommée à la fin de la ligne. Kusto conserve sa position d’origine ; reproduire ce comportement nécessiterait de connaître le schéma lors de l’analyse.
  • union exige que les opérandes aient des schémas compatibles. Kusto étend le résultat à l’union de toutes les colonnes et complète avec des valeurs nulles ; UNION ALL de ClickHouse ne le fait pas.
  • Les opérateurs sur les chaînes sont des fonctions de correspondance, et non des motifs LIKE. contains '50%' recherche un signe pour cent littéral.
  • geo_* prend la longitude avant la latitude, comme Kusto. geo_distance_2points utilise greatCircleDistance de ClickHouse, une approximation rapide qui diffère de Kusto au quatrième chiffre significatif — environ 600 m sur 1 500 km — et use_spheroid = true sélectionne geoDistance, la formule ellipsoïdale, comme dans Kusto. Une correspondance exacte n’est pas l’objectif : ces fonctions servent généralement au filtrage plutôt qu’à la génération de rapports. Notez qu’une coordonnée hors de [-180, 180] ou [-90, 90] produit un nombre dénué de sens plutôt que la valeur nulle renvoyée par Kusto : aucune fonction ClickHouse ne vérifie la plage de ses arguments, et cette vérification coûterait huit comparaisons par ligne.
  • dayofweek() renvoie une durée, et non un nombre : un lundi vaut 1.00:00:00.
  • tohex() affiche une valeur négative sur 64 bits. Kusto l’affiche selon la largeur du propre type de l’argument, ce qui n’est pas visible lors de l’analyse.
  • Les valeurs date-heure sont de véritables valeurs DateTime64, elles s’affichent donc au format ClickHouse (2017-01-01 00:00:00) plutôt qu’au format Kusto (2017-01-01T00:00:00.0000000). L’implémentation précédente produisait une chaîne formatée, qui ressemblait à Kusto mais ne pouvait pas être comparée ou triée comme une valeur date-heure.
  • Les agrégats paramétriques de ClickHouse (quantileExact(0.5)(x)) n’ont pas d’équivalent en KQL. Utilisez une alternative nommée telle que medianExact(x).

Signaler un problème

Une requête qui s’analyse correctement mais renvoie un résultat que Kusto ne renverrait pas est un bogue — veuillez le signaler en indiquant les deux résultats. Une requête rejetée dont vous avez besoin relève d’une demande de fonctionnalité ; les listes ci-dessus délimitent le périmètre plutôt que d’énumérer chaque nom rejeté — l’erreur d’analyse elle-même fait foi pour toute requête donnée — et rien de tout cela n’est définitif.
Dernière modification le 26 septembre 2026