تُعد دوال النافذة أقوى ميزة في SQL تفصل المحللين المبتدئين عن الكبار. تظهر هذه الدوال في كل مقابلة فنية تقريبًا في كبرى الشركات - ويفشل معظم المرشحين في حلها تمامًا.
يشرح هذا الدليل كل دالة نافذة مهمة مع أمثلة حقيقية، وأسئلة مقابلة، والأنماط الدقيقة التي تُطرح في Deloitte وAmazon وMcKinsey.
ما هي دالة النافذة؟
تؤدي دالة النافذة عملية حسابية عبر مجموعة من الصفوف المتعلقة بالصف الحالي - دون دمجها كما تفعل GROUP BY. تحتفظ بجميع صفوفك الأصلية وتحصل على العملية الحسابية.
المفتاح هو عبارة OVER():
-- GROUP BY: تدمج إلى صف واحد لكل قسم
SELECT dept, AVG(salary)
FROM employees
GROUP BY dept;
-- دالة النافذة: تحتفظ بجميع الصفوف، وتضيف متوسط الراتب لكل قسم
SELECT name, dept, salary,
AVG(salary) OVER (PARTITION BY dept) AS dept_avg
FROM employees;يعطي الاستعلام الثاني اسم كل موظف، وراتبه، ومتوسط قسمه - كل ذلك في صف واحد. هذا هو الفرق في دالة النافذة.
PARTITION BY مقابل ORDER BY
تقوم PARTITION BY بتقسيم الصفوف إلى مجموعات (دون دمجها). تتحكم ORDER BY في الترتيب داخل كل مجموعة - وهي ضرورية للترتيب والمجاميع الجارية.
-- إجمالي المبيعات الجاري، يُعاد تعيينه لكل منتج
SELECT product, sale_date, amount,
SUM(amount) OVER (
PARTITION BY product
ORDER BY sale_date
ROWS UNBOUNDED PRECEDING
) AS running_total
FROM sales;ROW_NUMBER وRANK وDENSE_RANK
دوال الترتيب الأكثر شيوعًا - والأكثر سوء فهمًا. تتصرف بشكل مختلف عندما يكون هناك تعادلات:
| الدالة | سلوك التعادل | الناتج |
|---|---|---|
| ROW_NUMBER() | دائما فريدة | 1, 2, 3, 4 |
| RANK() | نفس الترتيب للتعادلات، يتخطى التالي | 1, 1, 3, 4 |
| DENSE_RANK() | نفس الترتيب للتعادلات، لا توجد فجوة | 1, 1, 2, 3 |
SELECT name, dept, salary,
RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS dept_rank
FROM employees;LAG وLEAD - مقارنات الفترات
تحصل LAG على القيمة من صف سابق. تحصل LEAD على القيمة من صف مستقبلي. كلاهما حاسم للمقارنات الشهرية أو السنوية.
-- التغير في الإيرادات شهريًا
SELECT month, revenue,
LAG(revenue, 1) OVER (ORDER BY month) AS prev_month,
revenue - LAG(revenue, 1) OVER (ORDER BY month) AS change,
ROUND(100.0 * (revenue - LAG(revenue, 1) OVER (ORDER BY month))
/ LAG(revenue, 1) OVER (ORDER BY month), 1) AS pct_change
FROM monthly_revenue;NTILE - أوعية النسب المئوية
تقوم NTILE بتقسيم الصفوف إلى N أوعية متساوية. مثالية لتحليل الأرباع، أو أفضل/أسوأ 10%، أو تقسيم العملاء.
-- تقسيم العملاء إلى أربعة أرباع إنفاقية
SELECT customer_id, total_spend,
NTILE(4) OVER (ORDER BY total_spend DESC) AS quartile
FROM customers;
-- الربع الأول = أعلى 25% من المنفقينسؤال المقابلة الكلاسيكي
إليك أحد أسئلة المقابلات الأكثر شيوعًا في دوال النافذة:
"اكتب استعلامًا لإيجاد ثاني أعلى راتب في كل قسم."
WITH ranked AS (
SELECT name, dept, salary,
DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rnk
FROM employees
)
SELECT name, dept, salary
FROM ranked
WHERE rnk = 2;يتم استخدام DENSE_RANK هنا (وليس RANK) بحيث إذا تشارك شخصان في أعلى راتب، فإن الراتب الثاني المميز لا يزال يُصنف في المرتبة 2.
تدرب على هذه حتى تصبح تلقائية
المحللون الذين يتم توظيفهم ليسوا بالضرورة الأذكى - بل هم الأكثر ممارسة. استخدم مشاكل قاعدة بيانات LeetCode (قم بالتصفية حسب دوال النافذة)، ودورة SQL التعليمية من Mode Analytics، وورقة غش SQL الخاصة بنا للتدرب على هذه الأنماط حتى تشعر بأنها طبيعية.