Skip to main content
ClickHouse может разбирать подмножество запросов на Kusto Query Language вместо SQL. Этот диалект экспериментальный и по умолчанию отключён:
SET dialect = 'clickhouse' переключает обратно. SET — единственный SQL-оператор, распознаваемый при активном диалекте KQL, поэтому из него всегда можно выйти в рамках сеанса.

Что поддерживается

Это намеренно ограниченное подмножество. Конструкция KQL либо преобразуется с семантикой, задокументированной Kusto, либо отклоняется с ошибкой разбора — никакие приближения не выполняются молча. Если запрос успешно разбирается, его результат должен соответствовать результату в Kusto. Источники: имя таблицы, print, datatable, range, конвейер в скобках и union. range может задаваться от числа с числовым шагом, от даты и времени с шагом в виде временного интервала или от временного интервала с шагом в виде временного интервала. Операторы: 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. Скалярные операторы: ==, !=, <, <=, >, >=, =~, !~, in, in~, between, contains, startswith, endswith, has, hasprefix, hassuffix, их варианты с _cs (с учётом регистра) и ! (отрицанием), has_any, has_all и matches regex. in и !in также принимают табличное выражение, значения берутся из первого столбца (x in (T | project key)); in~ принимает только список. Одиночное имя внутри in (...), не связанное через let, интерпретируется как столбец, поскольку у анализатора нет схемы, позволяющей отличить столбец от таблицы; свяжите таблицу с помощью let, укажите её полное имя (db.table) или добавьте конвейер, чтобы получить табличную форму. Команды: let, связывающий скалярное значение, целое табличное выражение или функцию:
Функции принимают скалярные параметры с необязательными литеральными значениями по умолчанию, а также табличные параметры, объявленные как T: (*) или T: (col: type, ...); табличные параметры должны идти первыми. Табличный параметр с явно указанными столбцами предоставляет телу функции только эти столбцы аргумента, поэтому тело, обращающееся к необъявленному столбцу, отклоняется, даже если этот столбец есть в конкретном аргументе; T: (*) передаёт аргумент без изменений. Объявленные типы проверяются на границе вызова: аргумент (или объявленный столбец табличного аргумента), тип которого не относится к объявленному типу KQL, отклоняется; применяется преобразование без потери данных, например из long в real, а значение, не помещающееся в объявленный тип — например, при переполнении int, — вызывает ошибку, а не молча усекается. Аргументы можно передавать по имени в любом порядке (f(c = 7, a = 12)). Тело состоит из произвольного числа операторов let, за которыми следует одно выражение, и имеет доступ к охватывающим его привязкам. Функция, тело которой представляет собой конвейер, возвращает таблицу, а не значение, поэтому она отклоняется там, где ожидается выражение — в extend, where или print. Функцию без параметров можно вызывать как со скобками, так и без них. view () допускается и, поскольку здесь не разрешаются подстановочные шаблоны union *, означает то же самое, что и (). Рекурсия отклоняется, как и в Kusto. let создаёт привязку только для следующего за ним оператора, поскольку один оператор KQL — это один запрос к ClickHouse; это также предотвращает утечку привязки в параллельный запрос. Имя, необходимое в двух операторах, нужно привязать дважды. Литералы: строки (включая дословные @'...'), числа, datetime(...), guid(...), интервалы времени, например 1d / 2.5h / 500ms, и массивы dynamic([...]). Поддерживается около 130 скалярных и агрегатных функций. Как и в Kusto, агрегатные функции можно вызывать только в списке агрегации summarize; print count() отклоняется, а не передаётся одноимённой агрегатной функции ClickHouse. Функции ClickHouse также доступны. Имя, неизвестное реестру KQL, передаётся в ClickHouse в написанном вами виде, поэтому в запросе можно использовать всё, что предоставляет сервер:
Исключение — имена, определённые в самом Kusto, но не реализованные в этом диалекте: они отклоняются, а не передаются дальше, поэтому имя Kusto не может незаметно приобрести другое значение. Наиболее наглядный пример — range: range(1, 3, 1) в Kusto возвращает [1, 2, 3], а в ClickHouse — [1, 2], поэтому его использование в KQL приводит к ошибке, а не к неверному результату.

Покрытие относительно справочника Kusto

Согласно собственным справочникам Microsoft (табличные операторы, скалярные функции, агрегатные функции): Поддерживаются операторы из руководства Microsoft Learn common operators, а также datatable, range, print, union и join — этого достаточно для типов запросов, рассматриваемых в этом руководстве и KQL Quick Reference.

Что не поддерживается

Вместо неточного перевода отклоняется с ошибкой разбора:
  • Операторы: search, parse, mv-apply, lookup, evaluate, invoke, facet, top-nested, make-series, sample, serialize, partition, range в качестве оператора.
  • Функции: семейство series_*, bag_* / pack_*, parse_url, parse_csv, parse_json, todynamic, toscalar, format_timespan, format_datetime, extract_all, range, семейство percentiles* и оконные функции row_*. (format_datetime и extract_all отклоняются, а не аппроксимируются: спецификаторы формата yyyy-MM-dd в Kusto отличаются от используемых в ClickHouse, а extract_all в Kusto возвращает по одному массиву на каждую группу захвата.)
  • Имена Kusto, совпадающие с функциями ClickHouse, но имеющие другое значение: range (указана выше), repeat, replace, translate и materialize. Их прямое преобразование незаметно дало бы другой результат: repeat(1, 3) в Kusto создаёт массив [1, 1, 1], тогда как repeat в ClickHouse повторяет строку, поэтому все эти имена отклоняются.
  • Геопространственные функции, принимающие или возвращающие GeoJSON: все geo_*_to_central_point и всё, что работает с полигонами и линиями. Функции для точек, Geohash и H3, работающие с обычными значениями долготы и широты, поддерживаются. geo_point_to_s2cell не поддерживается: в ClickHouse нет представления S2 в виде токена.
  • Объекты dynamic (dynamic({"a": 1})), доступ к членам (x.y) и поиск по ключу (x['k']). Сопоставляются только массивы dynamic — с Array в ClickHouse. dynamic как объявленный тип — в схеме datatable, typeof(...) или параметре функции — также отклоняется: аннотация не содержит тип элемента, поэтому его невозможно сопоставить без потери точности.
  • Межкластерные и межбазовые ссылки, такие как cluster(...) и database(...).
  • Подсказки для запросов и join (hint.strategy, hint.shufflekey, …).
  • Параметры операторов: mv-expand ... to typeof(T) / limit N / bagexpansion, подсказки summarize, union kind= / withsource= / isfuzzy=, join hint.*.
  • Шаблоны столбцов с подстановочными знаками в project-away и project-keep (project-away Tmp*): для раскрытия такого шаблона нужна схема, которая недоступна при разборе. Перечислите столбцы явно.
  • Механизм плагинов evaluate целиком, а вместе с ним bag_unpack, pivot, narrow, python, R и остальные.
  • Операторы приложения: alias database, declare pattern, declare query_parameters, restrict access to.
  • Обфусцированные строковые литералы (h"...") и многострочные литералы (тройные обратные апострофы).

Важные особенности поведения

  • Временные интервалы — это значения Interval. 1d преобразуется в toIntervalNanosecond(86400000000000). Чтобы отображать их в формате Kusto (1.00:00:00), а не в виде числа, задайте interval_output_format = 'kusto'.
  • Деление выполняется как в Kusto: 7 / 2 равно 3, поскольку оба операнда — целые числа, а результат деления временного интервала на временной интервал — вещественное отношение (15ms / 10ms равно 1.5). Это реализовано в kqlDivide, которая определяет поведение по типам аргументов.
  • Вычитание двух значений даты и времени даёт число секунд, тогда как Kusto возвращает временной интервал. Сложение и вычитание временных интервалов работают ожидаемым образом.
  • sort по умолчанию сортирует по убыванию, в отличие от SQL, и помещает null-значения в начало.
  • project-rename перемещает переименованный столбец в конец строки. Kusto сохраняет его исходную позицию; для воспроизведения этого потребовалось бы знать схему при разборе.
  • union требует, чтобы операнды имели совместимые схемы. Kusto расширяет схему до объединения всех столбцов и дополняет отсутствующие значения null; UNION ALL в ClickHouse этого не делает.
  • Строковые операторы — это функции сопоставления, а не шаблоны LIKE. contains '50%' ищет буквальный знак процента.
  • geo_* принимает долготу перед широтой, как и Kusto. geo_distance_2points использует greatCircleDistance ClickHouse — быстрое приближение, которое отличается от Kusto в четвёртой значащей цифре — примерно на 600 м при расстоянии 1500 км, — а use_spheroid = true выбирает geoDistance, формулу эллипсоида, как в Kusto. Точное совпадение не является целью: эти функции обычно используются для фильтрации, а не для отчётности. Обратите внимание, что координата вне диапазона [-180, 180] или [-90, 90] даёт бессмысленное число, а не null, который возвращает Kusto: ни одна из функций ClickHouse не проверяет диапазон аргументов, а такая проверка потребовала бы восьми сравнений на строку.
  • dayofweek() возвращает временной интервал, а не число: понедельник — это 1.00:00:00.
  • tohex() выводит отрицательное значение с разрядностью 64 бита. Kusto выводит его с разрядностью, соответствующей типу самого аргумента, который не виден при разборе.
  • Значения даты и времени — это настоящие значения DateTime64, поэтому они выводятся в формате ClickHouse (2017-01-01 00:00:00), а не в формате Kusto (2017-01-01T00:00:00.0000000). Предыдущая реализация создавала форматированную строку, которая выглядела как в Kusto, но не сравнивалась и не сортировалась как дата и время.
  • Параметрические агрегатные функции ClickHouse (quantileExact(0.5)(x)) не имеют аналога в KQL. Используйте именованную альтернативу, например medianExact(x).

Сообщение о проблеме

Если запрос разбирается, но возвращает результат, который Kusto не вернул бы, это ошибка — сообщите о ней, приложив оба результата. Если нужный вам запрос отклоняется, это запрос на новую возможность; приведённые выше списки лишь очерчивают границу, а не перечисляют все отклоняемые имена — окончательный ответ для конкретного запроса даёт сама ошибка разбора, и ничто из этого не является окончательным.
Последнее изменение 26 сентября 2026 г.