> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-vortex-format.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Kusto Query Language ‏(KQL) في ClickHouse

> ما تدعمه لهجة KQL التجريبية وما لا تدعمه عمدًا

يمكن لـ ClickHouse تحليل مجموعة فرعية من [Kusto Query Language](https://learn.microsoft.com/en-us/kusto/query/)
بدلًا من SQL. هذه اللهجة **تجريبية** وتكون معطلة افتراضيًا:

```sql theme={null}
SET allow_experimental_kusto_dialect = 1;
SET dialect = 'kusto';

StormEvents
| where State == 'FLORIDA' and DamageProperty > 0
| summarize Total = sum(DamageProperty) by EventType
| top 5 by Total
```

يُعيد `SET dialect = 'clickhouse'` التبديل إلى ClickHouse. تُعد `SET` عبارة SQL الوحيدة التي يُتعرّف عليها أثناء
تفعيل لهجة KQL، لذا يمكن للجلسة دائمًا الخروج من هذا الوضع.

<h2 id="what-is-supported">
  العناصر المدعومة
</h2>

هذه مجموعة فرعية محدودة عمدًا. يُترجَم أي تركيب في KQL وفق الدلالات التي
يوثّقها Kusto، أو يُرفَض بالاسم مع ظهور خطأ تحليل — ولا تُجرى أي تقريبـات بصمت.
إذا أمكن تحليل استعلام، فيُفترض أن تطابق نتيجته نتيجة Kusto's.

**المصادر**: اسم جدول، و`print`، و`datatable`، و`range`، وخط أنابيب بين قوسين، و`union`.
يمتد `range` من رقم بزيادة رقم، أو من قيمة datetime بزيادة timespan، أو من قيمة timespan بزيادة
timespan.

**العوامل**: `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`، لربط قيمة قياسية، أو تعبير جدولي كامل، أو **دالة**:

```sql theme={null}
let MultiplyByN = (val: long, n: long = 2) { val * n };
let RecentErrors = (since: timespan) { Logs | where Level == 'Error' and Timestamp > ago(since) };

RecentErrors(1h) | summarize Count = count() by Component
```

تأخذ الدوال معاملات قياسية بقيم افتراضية حرفية اختيارية، ومعاملات جدولية
معلنة بصيغة `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 بالتهجئة التي كتبتها، لذا يمكن للاستعلام استخدام أي دالة يتيحها الخادم:

```sql theme={null}
SET dialect = 'kusto';

StormEvents
| extend Bucket = toStartOfHour(StartTime), Fingerprint = cityHash64(EventType)
| summarize Events = count() by Bucket
```

الاستثناء هو الأسماء التي يعرّفها Kusto نفسه ولا تنفذها هذه اللهجة؛ إذ تُرفض
بدلًا من تمريرها، لذلك لا يمكن أن يحمل اسم في Kusto معنى آخر دون تنبيه. وتُعد `range` أوضح مثال —
فـ`range(1, 3, 1)` تساوي `[1, 2, 3]` في Kusto و`[1, 2]` في
ClickHouse، لذا فإن استخدامها في KQL يُعد خطأً بدلًا من أن ينتج إجابة خاطئة.

<h2 id="coverage-against-the-kusto-reference">
  مدى التغطية مقارنةً بمرجع Kusto
</h2>

بالقياس إلى فهارس Microsoft الخاصة
([العوامل الجدولية](https://learn.microsoft.com/en-us/kusto/query/queries)،
[الدوال القياسية](https://learn.microsoft.com/en-us/kusto/query/scalar-functions)،
[دوال التجميع](https://learn.microsoft.com/en-us/kusto/query/aggregation-functions)):

| | مستندات Kusto | المدعوم هنا |
| - | - | - |
| العوامل الجدولية | 52 | 20 |
| الدوال القياسية ودوال التجميع | 307 | 162 |
| الدوال المعرّفة من قبل المستخدم | نعم | نعم |

تشمل العوامل المدعومة تلك التي يشرحها دليل Microsoft العملي *Learn common operators*،
إضافةً إلى `datatable` و`range` و`print` و`union` و`join`، وهي كافية لبنية الاستعلامات التي
يتدرج في بنائها ذلك الدليل ومرجع KQL السريع.

<h2 id="what-is-not-supported">
  ما لا تدعمه الأداة
</h2>

تُرفض هذه العناصر بخطأ تحليل بدلًا من ترجمتها ترجمة غير صحيحة:

* العوامل: `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"..."`) والقيم الحرفية متعددة الأسطر (ثلاث علامات اقتباس عكسية).

<h2 id="behaviour-worth-knowing">
  سلوكيات ينبغي معرفتها
</h2>

* **الفترات الزمنية هي قيم `Interval`.** يتحول `1d` إلى `toIntervalNanosecond(86400000000000)`.
  اضبط `interval_output_format = 'kusto'` لعرضها بتنسيق Kusto (`1.00:00:00`) بدلًا
  من رقم.
* **تتبع القسمة سلوك 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)`.

<h2 id="reporting-a-problem">
  الإبلاغ عن مشكلة
</h2>

إذا كان الاستعلام يُحلَّل لكنه يُرجع نتيجة لا يُرجعها Kusto، فهذا خلل — يُرجى الإبلاغ عنه مع
كلتا النتيجتين. أما الاستعلام الذي يُرفض وتحتاج إليه، فهو طلب ميزة؛ إذ توضح القوائم
أعلاه الحدود العامة بدلًا من حصر كل اسم مرفوض — ورسالة خطأ التحليل
نفسها هي المرجع النهائي لأي استعلام محدد — ولا شيء من ذلك دائم.
