إتقان SQL للمقابلات
أنماط SQL المتقدمة
هذه الأنماط تظهر في مقابلات علوم البيانات للمستويات العليا. تختبر قدرتك على حل المشاكل المعقدة بكفاءة وكتابة استعلامات قابلة للصيانة.
Self-Joins للبيانات الهرمية
Self-joins تتيح لك مقارنة الصفوف داخل نفس الجدول - شائعة لهرميات الموظفين ومقارنات السلاسل الزمنية.
مثال: جد الموظفين ومديريهم
SELECT
e.name as employee,
e.salary as employee_salary,
m.name as manager,
m.salary as manager_salary
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.employee_id;
سؤال مقابلة: "جد الموظفين الذين يكسبون أكثر من مديرهم"
SELECT e.name, e.salary, m.name as manager, m.salary as manager_salary
FROM employees e
INNER JOIN employees m ON e.manager_id = m.employee_id
WHERE e.salary > m.salary;
CTEs مقابل Subqueries
تعبيرات الجداول الشائعة (CTEs) تجعل الاستعلامات المعقدة قابلة للقراءة. محركات SQL الحديثة تحسنها بنفس مستوى الاستعلامات الفرعية.
نهج الاستعلام الفرعي (أصعب للقراءة):
SELECT customer_id, order_count
FROM (
SELECT customer_id, COUNT(*) as order_count
FROM orders
GROUP BY customer_id
) sub
WHERE order_count > (
SELECT AVG(order_count)
FROM (
SELECT customer_id, COUNT(*) as order_count
FROM orders
GROUP BY customer_id
) sub2
);
نهج CTE (أنظف):
WITH customer_orders AS (
SELECT customer_id, COUNT(*) as order_count
FROM orders
GROUP BY customer_id
),
avg_orders AS (
SELECT AVG(order_count) as avg_count
FROM customer_orders
)
SELECT co.customer_id, co.order_count
FROM customer_orders co
CROSS JOIN avg_orders ao
WHERE co.order_count > ao.avg_count;
متى تستخدم CTEs:
- منطق الاستعلام يحتاج للإشارة إليه عدة مرات
- تحويلات معقدة متعددة الخطوات
- استعلامات تكرارية (هياكل المنظمات، أشجار الفئات)
CTEs التكرارية
التعامل مع البيانات الهرمية مثل هياكل المنظمات أو أشجار الفئات:
-- احصل على كل المرؤوسين تحت مدير
WITH RECURSIVE subordinates AS (
-- الحالة الأساسية: التقارير المباشرة
SELECT employee_id, name, manager_id, 1 as level
FROM employees
WHERE manager_id = 100 -- المدير المبدئي
UNION ALL
-- الحالة التكرارية: تقارير التقارير
SELECT e.employee_id, e.name, e.manager_id, s.level + 1
FROM employees e
INNER JOIN subordinates s ON e.manager_id = s.employee_id
)
SELECT * FROM subordinates;
معالجة التاريخ/الوقت
دوال التاريخ تختلف حسب قاعدة البيانات، لكن الأنماط الأساسية عالمية:
-- استخراج أجزاء التاريخ
SELECT
order_date,
EXTRACT(YEAR FROM order_date) as year,
EXTRACT(MONTH FROM order_date) as month,
EXTRACT(DOW FROM order_date) as day_of_week, -- 0=الأحد
DATE_TRUNC('month', order_date) as month_start
FROM orders;
-- حساب التواريخ
SELECT
order_date,
order_date + INTERVAL '7 days' as week_later,
order_date - INTERVAL '1 month' as month_ago,
CURRENT_DATE - order_date as days_since_order
FROM orders;
نمط مقابلة شائع: "احسب معدل الاحتفاظ لـ 7 أيام"
WITH first_purchase AS (
SELECT
user_id,
MIN(order_date) as first_order_date
FROM orders
GROUP BY user_id
),
retained AS (
SELECT
fp.user_id,
fp.first_order_date,
CASE WHEN EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = fp.user_id
AND o.order_date BETWEEN fp.first_order_date + INTERVAL '1 day'
AND fp.first_order_date + INTERVAL '7 days'
) THEN 1 ELSE 0 END as is_retained
FROM first_purchase fp
)
SELECT
ROUND(100.0 * SUM(is_retained) / COUNT(*), 2) as retention_rate_7d
FROM retained;
اعتبارات الأداء
المُحاورون قد يسألون عن تحسين الاستعلامات:
| النمط | تأثير الأداء |
|---|---|
| SELECT * | سيء - يجلب أعمدة غير ضرورية |
| فهارس مفقودة على أعمدة JOIN | سيء - مسح كامل للجدول |
| استعلام فرعي في WHERE مقابل JOIN | الاستعلام الفرعي غالباً أبطأ |
| DISTINCT على مجموعات بيانات كبيرة | مكلف - فكر في GROUP BY |
| دوال على أعمدة مفهرسة | يمنع استخدام الفهرس |
مثال: صديق للفهرس مقابل كاسر للفهرس
-- كاسر للفهرس (دالة على العمود)
WHERE YEAR(order_date) = 2025
-- صديق للفهرس (مقارنة نطاق)
WHERE order_date >= '2025-01-01' AND order_date < '2026-01-01'
في المقابلات، اذكر اعتبارات الأداء حتى لو لم يُطلب. يظهر أنك تفكر في أنظمة الإنتاج. :::