الانتقال إلى المحتوى الرئيسي
تتيح لك دوال النافذة إجراء عمليات حسابية عبر مجموعة من الصفوف المرتبطة بالصف الحالي. ويمكن استخدامها لإجراء عمليات حسابية مشابهة لتلك التي تُنفَّذ باستخدام الدوال التجميعية، لكنها تختلف في أن دالة النافذة لا تؤدي إلى تجميع الصفوف في ناتج واحد، بل تظل الصفوف الفردية مُعادة.

دوال النافذة القياسية

يدعم ClickHouse بنية SQL القياسية للنوافذ ودوال النافذة. يوضح الجدول أدناه الميزات المدعومة حاليًا:
الميزةمدعومة؟تعليق
تحديد نافذة مخصص (count(*) OVER (PARTITION BY id ORDER BY time DESC))
تعبيرات تتضمن دوال النافذة، مثل (count(*) OVER ()) / 2
عبارة WINDOW (SELECT ... FROM table WINDOW w AS (PARTITION BY id))
إطار ROWS
إطار RANGEيُستخدم افتراضيًا عندما لا يُحدَّد إطار بشكل صريح (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW).
صياغة INTERVAL لإطار DateTime RANGE OFFSETحدِّد عدد الثواني بدلًا من ذلك (RANGE يعمل مع أي نوع رقمي).
إطار GROUPS
حساب الدوال التجميعية على إطار (sum(value) OVER (ORDER BY time))جميع الدوال التجميعية مدعومة.
rank(), dense_rank()/denseRank(), row_number()
percent_rank()/percentRank()يحسب بكفاءة الترتيب النسبي لقيمة داخل قسم. ويستبدل بذلك حساب SQL يدويًا أطول وأكثر كلفةً من ناحية المعالجة، والمعبَّر عنه كما يلي: ifNull((rank() OVER (PARTITION BY x ORDER BY y) - 1) / nullif(count(1) OVER (PARTITION BY x) - 1, 0), 0).
cume_dist()يحسب التوزيع التراكمي لقيمة داخل مجموعة من القيم. ويُرجع النسبة المئوية للصفوف التي تكون قيمها أقل من قيمة الصف الحالي أو مساوية لها.
lag/lead(value, offset)يمكنك أيضًا استخدام أحد الحلول البديلة التالية:
1) any(value) OVER (... ROWS BETWEEN <offset> PRECEDING AND <offset> PRECEDING)، أو FOLLOWING بدلًا من PRECEDING في حالة lead
2) lagInFrame/leadInFrame، وهما متشابهان لكنهما يراعيان إطار النافذة. للحصول على سلوك مطابق تمامًا لـ lag/lead، استخدم ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
ntile(buckets)حدِّد النافذة، على سبيل المثال، على النحو التالي: (PARTITION BY x ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING).

الصيغة

  • PARTITION BY - يحدّد كيفية تقسيم مجموعة النتائج إلى مجموعات.
  • ORDER BY - يحدّد كيفية ترتيب الصفوف داخل المجموعة أثناء حساب aggregate_function.
  • ROWS or RANGE - يحدّد حدود الإطار، ويُحسَب aggregate_function ضمن هذا الإطار.
  • WINDOW - يتيح لعدة تعبيرات استخدام تعريف النافذة نفسه.

الدوال التي لا يمكن استخدامها إلا كدوال نافذة

لا يمكن استخدام الدوال التالية إلا كدوال نافذة. معظمها دوال SQL قياسية، بينما تُعد lagInFrame وleadInFrame وnonNegativeDerivative امتدادات خاصة بـ ClickHouse.
FunctionDescription
row_number()رقِّم الصف الحالي داخل القسم الخاص به بدءًا من 1.
first_value(x)أرجِع أول قيمة جرى تقييمها ضمن الإطار المرتَّب.
last_value(x)أرجِع آخر قيمة جرى تقييمها ضمن الإطار المرتَّب.
nth_value(x, offset)أرجِع أول قيمة non-NULL جرى تقييمها عند الصف رقم n (offset) ضمن الإطار المرتَّب.
rank()امنح الصف الحالي ترتيبًا داخل القسم الخاص به مع وجود فجوات.
dense_rank()امنح الصف الحالي ترتيبًا داخل القسم الخاص به من دون فجوات.
lagInFrame(x)أرجِع قيمة جرى تقييمها عند صف يسبق الصف الحالي بإزاحة مادية محددة ضمن الإطار المرتَّب.
leadInFrame(x)أرجِع قيمة جرى تقييمها عند صف يلي الصف الحالي بعدد صفوف الإزاحة ضمن الإطار المرتَّب.
nonNegativeDerivative(metric_column, timestamp_column[, INTERVAL X UNITS])احسب المشتقة غير السالبة لـ metric_column بالنسبة إلى timestamp_column. هذه الدالة خاصة بـ ClickHouse.

أمثلة

لنلقِ نظرة على بعض الأمثلة لكيفية استخدام دوال النافذة.

ترقيم الصفوف

دوال التجميع

قارن راتب كل لاعب بمتوسط راتب فريقه.
قارن راتب كل لاعب بأقصى راتب في فريقه.

التقسيم حسب العمود

تعيين حدود الإطار

أمثلة واقعية

تتناول الأمثلة التالية مشكلات واقعية شائعة.

الحد الأقصى/إجمالي الرواتب لكل قسم

المجموع التراكمي

المتوسط المتحرك / المتوسط الانزلاقي (لكل 3 صفوف)

المتوسط المتحرك / المتوسط الانزلاقي (كل 10 ثوانٍ)

المتوسط المتحرك / المتوسط الانزلاقي (لكل 10 أيام)

تُخزَّن درجة الحرارة بدقة الثانية، ولكن باستخدام Range و ORDER BY toDate(ts) نُكوِّن إطارًا بحجم 10 وحدات، وبما أن toDate(ts) مستخدَمة هنا، فالوحدة هي اليوم.

المراجع

مشكلات GitHub

خطة الطريق للدعم الأولي لدوال النوافذ موجودة في هذه المشكلة. جميع مشكلات GitHub المتعلقة بدوال النوافذ تحمل الوسم comp-window-functions.

الاختبارات

تتضمن هذه الاختبارات أمثلة على البنية النحوية المدعومة حاليًا: https://github.com/ClickHouse/ClickHouse/blob/master/tests/performance/window&#95;functions.xml https://github.com/ClickHouse/ClickHouse/blob/master/tests/queries/0&#95;stateless/01591&#95;window&#95;functions.sql

وثائق Postgres

https://www.postgresql.org/docs/current/sql-select.html#SQL-WINDOW https://www.postgresql.org/docs/devel/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS https://www.postgresql.org/docs/devel/functions-window.html https://www.postgresql.org/docs/devel/tutorial-window.html

وثائق MySQL

https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html https://dev.mysql.com/doc/refman/8.0/en/window-functions-frames.html
آخر تعديل في ٢ يوليو ٢٠٢٦