مواضيع متقدمة في SQL


مواضيع متقدمة في SQL

مواضيع متقدمة في SQL

مرحباً! بما أنك وصلت هنا، فأنت بالتأكيد تجاوزت أساسيات SQL وتبحث عن طرق لجعل استعلاماتك أكثر قوة وفعالية. هذه بعض المواضيع المتقدمة اللي هتفيدك جداً في شغلك.

1. دوال النوافذ (Window Functions)

دوال النوافذ تسمح لك بإجراء عمليات حسابية (مثل المجموع، المتوسط، الترتيب) على مجموعة من الصفوف المرتبطة بالصف الحالي، بدون تجميع الصفوف باستخدام GROUP BY. يعني تقدر تشوف "نافذة" من البيانات وتطبق دالة عليها لكل صف على حدة. دي قوية جداً لتحليل البيانات.

التركيب الأساسي ليها بيكون بـ OVER(). داخل الأقواس دي ممكن تحدد:

  • PARTITION BY: لتقسيم البيانات إلى مجموعات (نوافذ) منفصلة.
  • ORDER BY: لترتيب الصفوف داخل كل نافذة.
  • ROWS BETWEEN أو RANGE BETWEEN: لتحديد نطاق الصفوف داخل النافذة (مثلاً، آخر 3 صفوف).

مثال: لو عايز تعرف ترتيب كل موظف داخل قسمه بناءً على الراتب:


SELECT
    employee_name,
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_department,
    AVG(salary) OVER (PARTITION BY department) as avg_dept_salary
FROM
    employees;
    

ملاحظة: دوال النوافذ ما بتأثرش على عدد الصفوف اللي بترجعها الاستعلام. كل صف موجود بيظهر مع القيمة المحسوبة.

2. التعبيرات الجدولية الشائعة (Common Table Expressions - CTEs)

الـ CTEs أو WITH clause، هي طريقة لتحديد مجموعة نتائج مؤقتة ومسماة، تقدر تشير ليها داخل استعلام SELECT، INSERT، UPDATE، أو DELETE. بتخلي استعلاماتك المعقدة أسهل في القراءة والفهم، وبتكسرها لأجزاء منطقية صغيرة. الـ CTE بيكون صالح للاستخدام فقط داخل الاستعلام اللي عرفته فيه.

التركيب بيكون كالتالي:


WITH SalesByYear AS (
    SELECT
        YEAR(order_date) as sales_year,
        SUM(total_amount) as total_sales
    FROM
        orders
    GROUP BY
        YEAR(order_date)
)
SELECT
    sales_year,
    total_sales
FROM
    SalesByYear
WHERE
    total_sales > 100000;
    

نصيحة: استخدم CTEs لما يكون عندك استعلامات فرعية (subqueries) متداخلة كتير، هتخلي الكود أنظف بكتير.

3. الـ CTEs التكرارية (Recursive CTEs)

دي نسخة أقوى من الـ CTEs العادية. بتسمح لك بالتعامل مع البيانات الهرمية أو الشجرية (زي هيكل تنظيمي لشركة، أو مسارات في شبكة). الـ Recursive CTE بيتكون من جزئين:

  • الجزء الأساسي (Anchor Member): ده الاستعلام الأول اللي بيحدد نقطة البداية للتكرار.
  • الجزء التكراري (Recursive Member): ده الاستعلام اللي بيشير لنفس الـ CTE وبيكرر العملية. لازم يكون فيه شرط توقف عشان ما يدخلش في حلقة لا نهائية.

مثال: لو عايز تجيب كل الموظفين اللي بيتبعوا لمدير معين في هيكل تنظيمي:


WITH EmployeeHierarchy AS (
    -- Anchor Member: Start with the top-level manager (or a specific employee)
    SELECT
        employee_id,
        employee_name,
        manager_id,
        1 as level
    FROM
        employees
    WHERE
        employee_id = 101 -- Let's say employee_id 101 is the CEO or a specific manager

    UNION ALL

    -- Recursive Member: Find direct reports of the previous level
    SELECT
        e.employee_id,
        e.employee_name,
        e.manager_id,
        eh.level + 1
    FROM
        employees e
    INNER JOIN
        EmployeeHierarchy eh ON e.manager_id = eh.employee_id
)
SELECT
    employee_id,
    employee_name,
    manager_id,
    level
FROM
    EmployeeHierarchy;
    

تنبيه: دايماً تأكد إنك حاطط شرط توقف في الـ Recursive CTE عشان ما يحصلش infinite loop.

4. الفهارس (Indexes)

الفهارس هي زي فهرس الكتاب، بتسرّع عملية البحث واسترجاع البيانات من الجداول. لما بتبحث عن صفوف في جدول كبير، من غير فهرس، قاعدة البيانات بتضطر تمسح الجدول كله (full table scan) عشان تلاقي اللي بتدور عليه. الفهرس بيوفر مسار سريع للوصول للبيانات.

أنواع الفهارس:

  • Clustered Index: بيحدد الترتيب الفيزيائي للصفوف في الجدول. الجدول ممكن يكون له فهرس clustered واحد بس. ده بيكون أسرع في استرجاع نطاق من البيانات.
  • Non-Clustered Index: ده ترتيب منطقي للبيانات، بيحتوي على مؤشرات (pointers) للموقع الفعلي للبيانات. الجدول ممكن يكون له فهارس non-clustered كتير.

إنشاء فهرس بسيط:


CREATE INDEX idx_employee_salary ON employees (salary);
    

وده مثال لإنشاء فهرس مركب (composite index) على أكتر من عمود:


CREATE INDEX idx_order_customer_date ON orders (customer_id, order_date);
    

ملحوظة مهمة: الفهارس بتسرّع عمليات القراءة (SELECT) لكنها ممكن تبطّئ عمليات الكتابة (INSERT, UPDATE, DELETE) لأن قاعدة البيانات بتحتاج تحدث الفهرس مع كل تغيير. استخدمها بحكمة!

دي كانت لمحة سريعة عن بعض المواضيع المتقدمة. فيه كتير تاني طبعاً، بس دول هيدوك دفعة قوية في رحلتك مع SQL. استمر في التعلم والتجربة!