0Pricing
Coding Interview Prep · درس

مجموعة مسائل مقابلة تجريبية كاملة

مسائل شاملة محددة بوقت تجمع بين عمليات الربط والنوافذ وCTE في ظروف المقابلة

مجموعة مسائل مقابلة تجريبية كاملة درس مجاني في Coding Interview Prep على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Coding Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Coding Interview Prep 4 دروس في المجموع.

كيف تسير جولة مقابلة SQL

يقدم لكم هذا القسم الختامي مسائل محاكاة كاملة تجمع بين عمليات JOIN ودوال النوافذ وCTE في ظروف المقابلة. أولًا، المهارة العامة: كيف تتصرفون أثناء المقابلة.

  • أعيدوا صياغة المسألة وتأكدوا من المخطط.
  • وضّحوا الحالات الطرفية، مثل NULLs والتعادلات والتكرارات، قبل كتابة التعليمات البرمجية.
  • اشرحوا نهجكم، ثم اكتبوا الاستعلام.
  • اختبروا الحل ذهنيًا على عينة صغيرة.

يقيّم القائمون بالمقابلة أسلوب عملكم بقدر تقييمهم للاستعلام النهائي.

المخطط المشترك

تستخدم جميع المسائل التالية مخطط التجارة الإلكترونية الصغير هذا. اقرأوه مرة واحدة حتى يصبح كل استعلام مفهومًا.

  • customers(id, name, country)
  • orders(id, customer_id, order_date, status, amount)
  • order_items(order_id, product_id, quantity)
  • products(id, name, category, price)

ضعوا هذا المخطط في اعتباركم؛ فبقية الدرس تشير إلى هذه الجداول.

-- orders.status is one of: 'paid','pending','cancelled'
-- amount is the order total in the customer's currency

المسألة 1: العملاء الأعلى إنفاقًا

«أعيدوا العملاء الثلاثة الأعلى من حيث إجمالي الإنفاق المدفوع، مع أسمائهم وإجمالي إنفاق كل منهم.»

النهج: اقتصِروا على الطلبات المدفوعة، ثم أجروا التجميع لكل عميل، ورتّبوا النتائج، وحددوا عددها. اذكروا أنكم تستبعدون الطلبات الملغاة والمعلّقة، فهذه حالة طرفية يضعها القائمون بالمقابلة عمدًا.

SELECT c.name,
       SUM(o.amount) AS total_spend
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY total_spend DESC
LIMIT 3;

المسألة 2: العملاء الذين لم يطلبوا قط

«اعرضوا العملاء الذين لم يضعوا أي طلب من قبل.» هذا هو نمط anti-join. وهناك حلان واضحان: استخدام LEFT JOIN مع IS NULL، أو استخدام NOT EXISTS.

فضّلوا NOT EXISTS لأنه آمن تجاه NULL، بخلاف NOT IN. اذكروا هذا الفرق؛ فهذا تحديدًا ما يحاول القائم بالمقابلة التحقق من معرفتكم به.

-- NULL-safe anti-join
SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

المسألة 3: ثاني أعلى قيمة طلب

«اعثروا على ثاني أعلى قيمة طلب مميزة.» يستخدم الحل الأبسط، الذي يتعامل مع التعادلات بأمان، DENSE_RANK بحيث تحصل القيم المتكررة على الترتيب نفسه.

الحالة الطرفية التي ينبغي ذكرها: إذا لم توجد قيمة مميزة ثانية، فلن يعيد هذا الحل أي صفوف، وقد يكون ذلك مقبولًا أو قد يتطلب تغليفه بـ COALESCE، حسب المتطلبات.

SELECT amount
FROM (
  SELECT amount,
         DENSE_RANK() OVER (ORDER BY amount DESC) AS rnk
  FROM orders
) ranked
WHERE rnk = 2;

المسألة 4: أحدث طلب لكل عميل

«أعيدوا أحدث طلب لكل عميل.» هذا هو نمط الاحتفاظ بأحدث صف لكل مفتاح، ويُحل باستخدام ROW_NUMBER مع التقسيم حسب العميل والترتيب حسب التاريخ تنازليًا.

أضيفوا فاصلًا للتعادلات، مثل معرّف الطلب، حتى تكون النتيجة حتمية عندما يشترك طلبان في التاريخ نفسه. وهذه تفصيلة يذكرها المرشحون الأقوياء.

SELECT customer_id, id AS order_id, order_date, amount
FROM (
  SELECT o.*,
         ROW_NUMBER() OVER (
           PARTITION BY customer_id
           ORDER BY order_date DESC, id DESC
         ) AS rn
  FROM orders o
) t
WHERE rn = 1;

المسألة 5: النمو من شهر إلى شهر

«احسبوا الإيرادات الشهرية المدفوعة ونسبة تغيرها مقارنةً بالشهر السابق.» يجمع هذا بين التجميع في CTE واستخدام LAG.

في الخطوة الأولى، أجروا التجميع حسب الشهر؛ وفي الخطوة الثانية، قارنوا كل شهر بالشهر السابق باستخدام LAG. احموا عملية القسمة حتى لا يحدث خطأ في الشهر الأول، إذ لا يسبقه شهر.

WITH monthly AS (
  SELECT DATE_TRUNC('month', order_date) AS mth,
         SUM(amount) AS revenue
  FROM orders
  WHERE status = 'paid'
  GROUP BY DATE_TRUNC('month', order_date)
)
SELECT mth,
       revenue,
       LAG(revenue) OVER (ORDER BY mth) AS prev_revenue,
       ROUND(
         100.0 * (revenue - LAG(revenue) OVER (ORDER BY mth))
         / NULLIF(LAG(revenue) OVER (ORDER BY mth), 0), 2
       ) AS pct_change
FROM monthly
ORDER BY mth;

المسألة 6: أفضل منتج لكل فئة

«لكل فئة، أعيدوا المنتج الأكثر مبيعًا من حيث إجمالي الكمية.» هذا هو نمط أعلى N لكل مجموعة: أجروا التجميع، ورتّبوا داخل كل partition، ثم صفّوا النتائج بحيث يساوي الترتيب 1.

إذا كانت التعادلات مهمة، فاستبدلوا ROW_NUMBER بـ RANK حتى تظهر جميع المنتجات المتصدرة بالتساوي. وذكر هذا الاختيار يوضح فهمكم للفرق بينهما.

WITH sales AS (
  SELECT p.category,
         p.name AS product,
         SUM(oi.quantity) AS qty
  FROM order_items oi
  JOIN products p ON p.id = oi.product_id
  GROUP BY p.category, p.name
)
SELECT category, product, qty
FROM (
  SELECT s.*,
         ROW_NUMBER() OVER (
           PARTITION BY category ORDER BY qty DESC
         ) AS rn
  FROM sales s
) r
WHERE rn = 1;

المسألة 7: الإجمالي التراكمي للإيرادات

«اعرضوا الإجمالي التراكمي للإيرادات المدفوعة حسب اليوم.» تنتج دالة النافذة SUM مع إطار مرتب الإجمالي التراكمي دون الحاجة إلى ربط الجدول بنفسه.

اذكروا استخدام إطار ROWS للحصول على تراكم حقيقي صفًا بصف؛ إذ قد يتصرف إطار RANGE الافتراضي بشكل غير متوقع مع التواريخ المتساوية.

SELECT order_date,
       SUM(daily) OVER (
         ORDER BY order_date
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ) AS running_total
FROM (
  SELECT order_date, SUM(amount) AS daily
  FROM orders
  WHERE status = 'paid'
  GROUP BY order_date
) d
ORDER BY order_date;

المسألة 8: الأيام النشطة المتتالية

«اعثروا على المستخدمين الذين لديهم ثلاثة أيام متتالية على الأقل تتضمن طلبًا مدفوعًا.» هذه صيغة من نمط gaps-and-islands تستخدم حيلة الفرق بين أرقام الصفوف.

يؤدي طرح رقم صف خاص بكل مستخدم من التاريخ إلى قيمة ثابتة ضمن السلسلة المتتالية، ولذلك يمكنكم التجميع حسب هذه القيمة ثم العد. وهذا مؤشر على مستوى متقدم.

WITH days AS (
  SELECT DISTINCT customer_id, order_date
  FROM orders WHERE status = 'paid'
),
grp AS (
  SELECT customer_id, order_date,
         order_date - (ROW_NUMBER() OVER (
           PARTITION BY customer_id ORDER BY order_date
         ) * INTERVAL '1 day') AS island
  FROM days
)
SELECT customer_id, COUNT(*) AS streak_len
FROM grp
GROUP BY customer_id, island
HAVING COUNT(*) >= 3;

الأداء والأخطاء الشائعة

بعد الوصول إلى استعلام صحيح، يسأل القائمون بالمقابلة: «كيف ستجعلونه أسرع؟» ويراقبون وقوعكم في الأخطاء التقليدية. احتفظوا بقائمة تحقق جاهزة:

  • فهرسوا أعمدة الربط والتصفية، مثل orders(customer_id, status)، وتجنبوا استخدام الدوال على الأعمدة المفهرسة في WHERE.
  • فضّلوا EXISTS على IN في عمليات anti-join الكبيرة؛ إذ يعيد NOT IN مع NULL لا شيء بصمت.
  • يؤدي تصفية عمود من عملية ربط خارجية في WHERE بهدوء إلى تحويلها إلى عملية ربط داخلية.
  • أضيفوا دائمًا فاصلًا للتعادلات حتى تكون نتائج أعلى N حتمية.
  • تحققوا من خطة EXPLAIN بحثًا عن عمليات المسح التسلسلي في الجداول الكبيرة.

تحقق سريع

تحتاجون إلى أحدث طلب واحد لكل عميل، ويمكن أن يشترك طلبان في التاريخ نفسه.

مراجعة: مجموعة مقابلات المحاكاة الكاملة

لقد حللتم أكثر مسائل المقابلات شيوعًا من البداية إلى النهاية:

  • التجميع مع LIMIT للحصول على أعلى N من حيث الإنفاق.
  • عمليات anti-join باستخدام NOT EXISTS، مع أمان تجاه NULL.
  • DENSE_RANK للحصول على الترتيب الأعلى رقم N، وROW_NUMBER للحصول على الأحدث لكل مفتاح والأعلى لكل مجموعة.
  • LAG للمقارنة من شهر إلى شهر، وSUM OVER للإجماليات التراكمية.
  • حيلة أرقام الصفوف في gaps-and-islands لاكتشاف السلاسل المتتالية.
  • اختتموا كل إجابة بمناقشة الفهارس وEXPLAIN والأخطاء الشائعة.

الأسئلة الشائعة

هل درس «مجموعة مسائل مقابلة تجريبية كاملة» مجاني؟

نعم — نص درس «مجموعة مسائل مقابلة تجريبية كاملة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Coding Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة Coding Interview Prep 4 دروس في المجموع.

ماذا ستتعلم في «مجموعة مسائل مقابلة تجريبية كاملة»؟

مسائل شاملة محددة بوقت تجمع بين عمليات الربط والنوافذ وCTE في ظروف المقابلة تتمرن على Coding Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Coding Interview Prep؟

لا تُشترط خبرة سابقة. Coding Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «مجموعة مسائل مقابلة تجريبية كاملة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Coding Interview Prep هذا؟

نعم. كل درس في Coding Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. التطبيع حتى 3NF
  2. نمذجة ER وتعددية العلاقات
  3. مخطط النجمة وتصميم مستودع البيانات
  4. مجموعة مسائل مقابلة تجريبية كاملة
← العودة إلى Coding Interview Prep