إتقان SQL للمقابلات
مسائل تدريب SQL
تدرب مع هذه المسائل الكلاسيكية للمقابلات. كل منها يظهر بشكل متكرر في الشركات التقنية الكبرى. حاول حلها قبل قراءة الحلول.
المسألة 1: ثاني أعلى راتب
السؤال: اكتب استعلاماً للحصول على ثاني أعلى راتب من جدول الموظفين. إذا لم يكن هناك ثاني أعلى راتب، أرجع NULL.
جدول Employee:
| id | salary |
|----|--------|
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
الحل:
SELECT MAX(salary) as SecondHighestSalary
FROM Employee
WHERE salary < (SELECT MAX(salary) FROM Employee);
بديل باستخدام DENSE_RANK:
WITH ranked AS (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) as rank
FROM Employee
)
SELECT MAX(salary) as SecondHighestSalary
FROM ranked
WHERE rank = 2;
المسألة 2: أيام تسجيل دخول متتالية
السؤال: جد المستخدمين الذين سجلوا دخولهم لـ 3 أيام متتالية أو أكثر.
جدول Logins:
| user_id | login_date |
|---------|------------|
| 1 | 2025-01-01 |
| 1 | 2025-01-02 |
| 1 | 2025-01-03 |
| 2 | 2025-01-01 |
| 2 | 2025-01-03 |
الحل:
WITH consecutive_groups AS (
SELECT
user_id,
login_date,
login_date - INTERVAL '1 day' * ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY login_date
) as grp
FROM (SELECT DISTINCT user_id, login_date FROM Logins) t
)
SELECT DISTINCT user_id
FROM consecutive_groups
GROUP BY user_id, grp
HAVING COUNT(*) >= 3;
الرؤية الأساسية: عندما تطرح رقماً تسلسلياً من تواريخ متتالية، تحصل على نفس قيمة "المجموعة". التواريخ غير المتتالية تنتج مجموعات مختلفة.
المسألة 3: أعلى N لكل مجموعة
السؤال: جد أعلى موظفين اثنين أجراً في كل قسم.
جدول Employee:
| id | name | salary | department |
|----|---------|--------|------------|
| 1 | Alice | 90000 | Engineering|
| 2 | Bob | 85000 | Engineering|
| 3 | Charlie | 80000 | Engineering|
| 4 | Diana | 70000 | Sales |
الحل:
WITH ranked AS (
SELECT
*,
DENSE_RANK() OVER (
PARTITION BY department
ORDER BY salary DESC
) as rank
FROM Employee
)
SELECT name, salary, department
FROM ranked
WHERE rank <= 2;
المسألة 4: كشف التكرارات
السؤال: جد كل الإيميلات المكررة في جدول Person.
جدول Person:
| id | email |
|----|------------------|
| 1 | a@example.com |
| 2 | b@example.com |
| 3 | a@example.com |
الحل:
SELECT email
FROM Person
GROUP BY email
HAVING COUNT(*) > 1;
إذا احتجت كل الأعمدة من الصفوف المكررة:
SELECT *
FROM Person
WHERE email IN (
SELECT email
FROM Person
GROUP BY email
HAVING COUNT(*) > 1
);
المسألة 5: المجاميع التراكمية حسب الفئة
السؤال: احسب المجموع التراكمي للمبيعات حسب الفئة، مرتبة حسب التاريخ.
جدول Sales:
| date | category | amount |
|------------|----------|--------|
| 2025-01-01 | A | 100 |
| 2025-01-02 | A | 150 |
| 2025-01-01 | B | 200 |
| 2025-01-02 | B | 50 |
الحل:
SELECT
date,
category,
amount,
SUM(amount) OVER (
PARTITION BY category
ORDER BY date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) as running_total
FROM Sales
ORDER BY category, date;
استراتيجية التدريب
لكل نوع مسألة، اتبع هذا النهج:
- وضّح: اسأل عن حالات الحافة (NULLs، التعادلات، الجداول الفارغة)
- فكر بصوت عالٍ: اشرح نهجك قبل الكتابة
- ابدأ بسيطاً: احصل على حل عامل أولاً
- حسّن: اذكر إذا كنت ستفعلها بشكل مختلف على نطاق واسع
- تحقق: امشِ خلال البيانات النموذجية
منصات المقابلات الشائعة: LeetCode (مسائل SQL)، DataLemur، StrataScratch، HackerRank
اهدف لحل 50+ مسألة قبل مقابلتك الأولى. الأنماط تصبح طبيعة ثانية. :::