الانتقال إلى المحتوى الرئيسي

نظرة عامة

استخدام النتائج الشرطية مباشرةً

تُرجع التعبيرات الشرطية دائمًا 0 أو 1 أو NULL. لذا يمكنك استخدام نتائجها مباشرةً كما يلي:
SELECT left < right AS is_small
FROM LEFT_RIGHT

┌─is_small─┐
│     ᴺᵁᴸᴸ │
1
0
0
│     ᴺᵁᴸᴸ │
└──────────┘

قيم NULL في التعبيرات الشرطية

عند وجود قيم NULL في التعبيرات الشرطية، تكون النتيجة أيضًا NULL.
SELECT
    NULL < 1,
    2 < NULL,
    NULL < NULL,
    NULL = NULL

┌─less(NULL, 1)─┬─less(2, NULL)─┬─less(NULL, NULL)─┬─equals(NULL, NULL)─┐
│ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ             │ ᴺᵁᴸᴸ               │
└───────────────┴───────────────┴──────────────────┴────────────────────┘
لذلك ينبغي إنشاء استعلاماتك بعناية إذا كانت الأنواع Nullable. ويوضح المثال التالي ذلك، إذ يفشل بسبب عدم إضافة شرط equals إلى multiIf.
SELECT
    left,
    right,
    multiIf(left < right, 'left is smaller', left > right, 'right is smaller', 'Both equal') AS faulty_result
FROM LEFT_RIGHT

┌─left─┬─right─┬─faulty_result────┐
│ ᴺᵁᴸᴸ │     4Both equal       │
13 │ left is smaller  │
22Both equal       │
31 │ right is smaller │
4 │  ᴺᵁᴸᴸ │ Both equal       │
└──────┴───────┴──────────────────┘

عبارة CASE

يوفّر التعبير CASE في ClickHouse منطقًا شرطيًا مشابهًا لمعامل CASE في SQL. إذ يقيّم الشروط ويُرجع القيم بناءً على أول شرط متطابق. يدعم ClickHouse شكلين لعبارة CASE:
  1. CASE WHEN ... THEN ... ELSE ... END
    يوفّر هذا الشكل مرونة كاملة، ويُنفَّذ داخليًا باستخدام الدالة multiIf. ويُقيَّم كل شرط على نحو مستقل، ويمكن أن تتضمن التعبيرات قيمًا غير ثابتة.
SELECT
    number,
    CASE
        WHEN number % 2 = 0 THEN number + 1
        WHEN number % 2 = 1 THEN number * 10
        ELSE number
    END AS result
FROM system.numbers
WHERE number < 5;

-- is translated to
SELECT
    number,
    multiIf((number % 2) = 0, number + 1, (number % 2) = 1, number * 10, number) AS result
FROM system.numbers
WHERE number < 5

┌─number─┬─result─┐
01
110
23
330
45
└────────┴────────┘

5 rows in set. Elapsed: 0.002 sec.
  1. CASE <expr> WHEN <val1> THEN ... WHEN <val2> THEN ... ELSE ... END
    هذا الشكل الأكثر اختصارًا مُحسَّن لمطابقة القيم الثابتة، ويستخدم داخليًا caseWithExpression().
على سبيل المثال، ما يلي صحيح:
SELECT
    number,
    CASE number
        WHEN 0 THEN 100
        WHEN 1 THEN 200
        ELSE 0
    END AS result
FROM system.numbers
WHERE number < 3;

-- is translated to

SELECT
    number,
    caseWithExpression(number, 0, 100, 1, 200, 0) AS result
FROM system.numbers
WHERE number < 3

┌─number─┬─result─┐
0100
1200
20
└────────┴────────┘

3 rows in set. Elapsed: 0.002 sec.
هذه الصيغة أيضًا لا تشترط أن تكون تعبيرات الإرجاع ثوابت.
SELECT
    number,
    CASE number
        WHEN 0 THEN number + 1
        WHEN 1 THEN number * 10
        ELSE number
    END
FROM system.numbers
WHERE number < 3;

-- is translated to

SELECT
    number,
    caseWithExpression(number, 0, number + 1, 1, number * 10, number)
FROM system.numbers
WHERE number < 3

┌─number─┬─caseWithExpr⋯0), number)─┐
01
110
22
└────────┴──────────────────────────┘

3 rows in set. Elapsed: 0.001 sec.

محاذير

يحدّد ClickHouse نوع نتيجة تعبير CASE (أو ما يكافئه داخليًا، مثل multiIf) قبل تقييم أي شروط. ويكتسب هذا أهمية عندما تختلف تعبيرات الإرجاع في النوع، مثل اختلاف المناطق الزمنية أو الأنواع الرقمية.
  • يُختار نوع النتيجة بناءً على أكبر نوع متوافق بين جميع الفروع.
  • وبمجرد اختيار هذا النوع، تُحوَّل جميع الفروع الأخرى إليه ضمنيًا - حتى إن كان منطقها لن يُنفَّذ مطلقًا أثناء التشغيل.
  • بالنسبة إلى أنواع مثل DateTime64، حيث تكون المنطقة الزمنية جزءًا من تعريف النوع، فقد يؤدي ذلك إلى سلوك غير متوقع: إذ قد تُستخدم أول منطقة زمنية تمت مصادفتها في جميع الفروع، حتى عندما تحدد الفروع الأخرى مناطق زمنية مختلفة.
على سبيل المثال، في ما يلي تُرجع جميع الصفوف الطابع الزمني وفق المنطقة الزمنية لأول فرع مطابق، أي Asia/Kolkata
SELECT
    number,
    CASE
        WHEN number = 0 THEN fromUnixTimestamp64Milli(0, 'Asia/Kolkata')
        WHEN number = 1 THEN fromUnixTimestamp64Milli(0, 'America/Los_Angeles')
        ELSE fromUnixTimestamp64Milli(0, 'UTC')
    END AS tz
FROM system.numbers
WHERE number < 3;

-- is translated to

SELECT
    number,
    multiIf(number = 0, fromUnixTimestamp64Milli(0, 'Asia/Kolkata'), number = 1, fromUnixTimestamp64Milli(0, 'America/Los_Angeles'), fromUnixTimestamp64Milli(0, 'UTC')) AS tz
FROM system.numbers
WHERE number < 3

┌─number─┬──────────────────────tz─┐
01970-01-01 05:30:00.000
11970-01-01 05:30:00.000
21970-01-01 05:30:00.000
└────────┴─────────────────────────┘

3 rows in set. Elapsed: 0.011 sec.
هنا، يرى ClickHouse عدة أنواع إرجاع DateTime64(3, <timezone>). ويستنتج أن النوع المشترك هو DateTime64(3, 'Asia/Kolkata' لأنه أول نوع يصادفه، ويحوّل الفروع الأخرى ضمنيًا إلى هذا النوع. يمكن معالجة ذلك بالتحويل إلى سلسلة نصية للحفاظ على تنسيق المنطقة الزمنية المطلوب:
SELECT
    number,
    multiIf(
        number = 0, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'Asia/Kolkata'),
        number = 1, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'America/Los_Angeles'),
        formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'UTC')
    ) AS tz
FROM system.numbers
WHERE number < 3;

-- is translated to

SELECT
    number,
    multiIf(number = 0, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'Asia/Kolkata'), number = 1, formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'America/Los_Angeles'), formatDateTime(fromUnixTimestamp64Milli(0), '%F %T', 'UTC')) AS tz
FROM system.numbers
WHERE number < 3

┌─number─┬─tz──────────────────┐
01970-01-01 05:30:00
11969-12-31 16:00:00
21970-01-01 00:00:00
└────────┴─────────────────────┘

3 rows in set. Elapsed: 0.002 sec.

clamp

قُدِّم في: v24.5.0 يقيّد قيمة لتبقى ضمن الحدين الأدنى والأقصى المحددين. إذا كانت القيمة أقل من الحد الأدنى، فسيُرجِع الحد الأدنى. وإذا كانت أكبر من الحد الأقصى، فسيُرجِع الحد الأقصى. وإلا فسيُرجِع القيمة نفسها. يجب أن تكون جميع الوسيطات من أنواع قابلة للمقارنة. ويكون نوع النتيجة أكبر نوع متوافق بين جميع الوسيطات. الصيغة
clamp(value, min, max)
الوسيطات
  • value — القيمة المطلوب تقييدها. - min — الحد الأدنى. - max — الحد الأقصى.
القيمة المُعادة تعيد القيمة بعد تقييدها ضمن النطاق [min, max]. أمثلة الاستخدام الأساسي
Query
SELECT clamp(5, 1, 10) AS result;
Response
┌─result─┐
│      5 │
└────────┘
القيمة دون الحد الأدنى
Query
SELECT clamp(-3, 0, 7) AS result;
Response
┌─result─┐
│      0 │
└────────┘
القيمة أكبر من الحد الأقصى
Query
SELECT clamp(15, 0, 7) AS result;
Response
┌─result─┐
│      7 │
└────────┘

greatest

أُضيفت في: v1.1.0 تعيد أكبر قيمة بين الوسيطات. يتم تجاهل الوسيطات NULL.
  • بالنسبة إلى المصفوفات، تعيد المصفوفة الأكبر ترتيبًا معجميًا.
  • بالنسبة إلى أنواع DateTime، تتم ترقية نوع النتيجة إلى أكبر نوع (مثلًا، DateTime64 عند مزجه مع DateTime32).
استخدم الإعداد least_greatest_legacy_null_behavior لتغيير سلوك NULLقدّم الإصدار 24.12 تغييرًا غير متوافق مع الإصدارات السابقة، بحيث يتم تجاهل قيم NULL، بينما كان يُرجِع سابقًا NULL إذا كانت إحدى الوسيطات NULL. للاحتفاظ بالسلوك السابق، اضبط الإعداد least_greatest_legacy_null_behavior (الافتراضي: false) على true.
الصياغة
greatest(x1[, x2, ...])
الوسائط
  • x1[, x2, ...] — قيمة واحدة أو عدة قيم للمقارنة. يجب أن تكون جميع الوسائط من أنواع قابلة للمقارنة. Any
القيمة المعادة تُرجِع أكبر قيمة بين الوسائط، مع ترقيتها إلى أوسع نوع متوافق. Any أمثلة الأنواع الرقمية
Query
SELECT greatest(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
-- The type returned is a Float64 as the UInt8 must be promoted to 64 bit for the comparison.
Response
┌─result─┬─type────┐
│      3 │ Float64 │
└────────┴─────────┘
المصفوفات
Query
SELECT greatest(['hello'], ['there'], ['world']);
Response
┌─greatest(['hello'], ['there'], ['world'])─┐
│ ['world']                                 │
└───────────────────────────────────────────┘
أنواع DateTime
Query
SELECT greatest(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3));
-- The type returned is a DateTime64 as the DateTime32 must be promoted to 64 bit for the comparison.
Response
┌─greatest(toD⋯(now(), 3))─┐
│  2025-05-28 15:50:53.000 │
└──────────────────────────┘

if

أُضيفت في: v1.1.0 تنفّذ التفريع الشرطي.
  • إذا قُيِّم الشرط cond إلى قيمة غير صفرية، فتعيد الدالة نتيجة التعبير then.
  • إذا قُيِّم cond إلى صفر أو NULL، فتُعاد نتيجة التعبير else.
يتحكّم الإعداد short_circuit_function_evaluation في ما إذا كان التقييم المختصر مستخدمًا. إذا كان مفعّلًا، فلا يُقيَّم التعبير then إلا على الصفوف التي تكون فيها قيمة cond هي true، ويُقيَّم التعبير else على الصفوف التي تكون فيها قيمة cond هي false. على سبيل المثال، عند استخدام التقييم المختصر، لا يُطرَح استثناء القسمة على صفر عند تنفيذ الاستعلام التالي:
SELECT if(number = 0, 0, intDiv(42, number)) FROM numbers(10)
يجب أن يكون then و else من نوعين متشابهين. الصيغة
if(cond, then, else)
الوسائط
  • cond — الشرط الذي يجري تقييمه. UInt8 أو Nullable(UInt8) أو NULL
  • then — التعبير المُعاد إذا كانت cond تساوي true. - else — التعبير المُعاد إذا كانت cond تساوي false أو NULL.
القيمة المُعادة ناتج أحد التعبيرين then أو else، حسب الشرط cond. أمثلة مثال على الاستخدام
Query
SELECT if(1, 2 + 2, 2 + 6) AS res;
Response
┌─res─┐
│   4 │
└─────┘

least

أُضيف في: v1.1.0 يعيد أصغر قيمة بين الوسائط. يتم تجاهل الوسائط NULL.
  • بالنسبة إلى المصفوفات، يعيد المصفوفة الأصغر ترتيبًا معجميًا.
  • بالنسبة إلى أنواع DateTime، يُرقّى نوع النتيجة إلى أكبر نوع (على سبيل المثال، DateTime64 عند دمجه مع DateTime32).
استخدم الإعداد least_greatest_legacy_null_behavior لتغيير سلوك NULLقدّم الإصدار 24.12 تغييرًا غير متوافق مع الإصدارات السابقة، بحيث يتم تجاهل قيم NULL، بينما كان يعيد سابقًا القيمة NULL إذا كان أحد الوسائط NULL. للاحتفاظ بالسلوك السابق، اضبط الإعداد least_greatest_legacy_null_behavior (القيمة الافتراضية: false) على true.
الصيغة
least(x1[, x2, ...])
الوسائط
  • x1[, x2, ...] — قيمة واحدة أو عدة قيم للمقارنة. يجب أن تكون جميع الوسائط من أنواع قابلة للمقارنة. Any
القيمة المُعادة تُعيد أصغر قيمة بين الوسائط، وتُرقّى إلى أكبر نوع متوافق. Any أمثلة الأنواع الرقمية
Query
SELECT least(1, 2, toUInt8(3), 3.) AS result, toTypeName(result) AS type;
-- The type returned is a Float64 as the UInt8 must be promoted to 64 bit for the comparison.
Response
┌─result─┬─type────┐
│      1 │ Float64 │
└────────┴─────────┘
المصفوفات
Query
SELECT least(['hello'], ['there'], ['world']);
Response
┌─least(['hell⋯ ['world'])─┐
│ ['hello']                │
└──────────────────────────┘
أنواع DateTime
Query
SELECT least(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3));
-- The type returned is a DateTime64 as the DateTime32 must be promoted to 64 bit for the comparison.
Response
┌─least(toDate⋯(now(), 3))─┐
│  2025-05-27 15:55:20.000 │
└──────────────────────────┘

multiIf

تم تقديمه في: v1.1.0 يتيح كتابة العامل CASE بصورة أكثر اختصارًا في الاستعلام. يُقيِّم كل شرط بالترتيب. وبالنسبة إلى أول شرط يكون صحيحًا (غير صفري وليس NULL)، يُرجِع قيمة الفرع المقابلة. إذا لم يكن أي من الشروط صحيحًا، فسيُرجِع قيمة else. يتحكم الإعداد short_circuit_function_evaluation في ما إذا كان التقييم المختصر مستخدمًا. وإذا كان مفعّلًا، فلن يُقيَّم التعبير then_i إلا على الصفوف التي تكون فيها ((NOT cond_1) AND ... AND (NOT cond_{i-1}) AND cond_i) صحيحة. على سبيل المثال، مع التقييم المختصر، لا يحدث استثناء قسمة على صفر عند تنفيذ الاستعلام التالي:
SELECT multiIf(number = 2, intDiv(1, number), number = 5) FROM numbers(10)
يجب أن يكون لجميع تعبيرات الفروع وelse نوع فائق مشترك. تُعامل الشروط ذات القيمة NULL على أنها false. الصيغة
multiIf(cond_1, then_1, cond_2, then_2, ..., else)
الأسماء البديلة: caseWithoutExpression, caseWithoutExpr الوسائط
  • cond_N — الشرط المُقيَّم رقم N الذي يحدد ما إذا كانت then_N ستُعاد. UInt8 أو Nullable(UInt8) أو NULL
  • then_N — ناتج الدالة عندما تكون cond_N صحيحة. - else — ناتج الدالة إذا لم يتحقق أي من الشروط.
القيمة المعادة تُعيد ناتج then_N الموافق لـ cond_N المطابق، وإلا فتُعيد قيمة else. أمثلة مثال على الاستخدام
Query
CREATE TABLE LEFT_RIGHT (left Nullable(UInt8), right Nullable(UInt8)) ENGINE = Memory;
INSERT INTO LEFT_RIGHT VALUES (NULL, 4), (1, 3), (2, 2), (3, 1), (4, NULL);

SELECT
    left,
    right,
    multiIf(left < right, 'left is smaller', left > right, 'left is greater', left = right, 'Both equal', 'Null value') AS result
FROM LEFT_RIGHT;
Response
┌─left─┬─right─┬─result──────────┐
│ ᴺᵁᴸᴸ │     4 │ Null value      │
│    1 │     3 │ left is smaller │
│    2 │     2 │ Both equal      │
│    3 │     1 │ left is greater │
│    4 │  ᴺᵁᴸᴸ │ Null value      │
└──────┴───────┴─────────────────┘
آخر تعديل في ٢٥ يونيو ٢٠٢٦