تحويل الأعمدة إلى صفوف
عكس الجداول العريضة باستخدام UNPIVOT أو UNION ALL
تحويل الأعمدة إلى صفوف درس مجاني في Coding Interview Prep على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Coding Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Coding Interview Prep 4 دروس في المجموع.
المشكلة العكسية
فكّ التدوير هو الصورة المعاكسة للتدوير: إذ تأخذ جدولًا عريضًا وتحول أعمدته مرة أخرى إلى صفوف. يطرح المحاوِرون هذا السؤال عندما تصل البيانات في هيئة جدول بيانات، لكنها تحتاج إلى التطبيع لأغراض التحليل.
مثال: يجب تحويل جدول يحتوي على الأعمدة q1, q2, q3, q4 لكل منطقة إلى صفوف من الشكل (region, quarter, amount). وهذا الشكل الطولي هو ما تفضله عمليات التجميع والضمّ وإنشاء المخططات.
-- Wide input we want to unpivot
region | q1 | q2 | q3 | q4
-------+-----+-----+-----+----
East | 100 | 150 | 120 | 180
West | 200 | 250 | 210 | 260النمط القابل للنقل باستخدام UNION ALL
الإجابة المستقلة عن اللهجة هي UNION ALL: اكتب عبارة SELECT واحدة لكل عمود مصدر، بحيث تُخرج كل عبارة تسمية حرفية وقيمة ذلك العمود.
استخدم UNION ALL لا UNION، حتى لا تتحمل تكلفة إزالة التكرارات، ولتحافظ على كل صف، حتى عندما تتشارك خليتان في القيمة نفسها.
SELECT region, 'Q1' AS quarter, q1 AS amount FROM wide_sales
UNION ALL
SELECT region, 'Q2', q2 FROM wide_sales
UNION ALL
SELECT region, 'Q3', q3 FROM wide_sales
UNION ALL
SELECT region, 'Q4', q4 FROM wide_sales;لماذا UNION ALL وليس UNION
هذا فخ شائع في المقابلات. يزيل UNION الصفوف المكررة من النتيجة بأكملها. فإذا كانت المنطقتان East وWest تحتويان على 100 في الربع الأول، فسيطوي UNION العادي الصفوف المتطابقة وستفقد البيانات.
تضمّ UNION ALL النتائج دون إزالة التكرارات، وهذا هو المطلوب عند فكّ التدوير. كما أنها أسرع، لأنها لا تحتاج إلى فرز أو تجزئة لإزالة التكرارات.
-- UNION would wrongly merge identical (region, quarter, amount) rows
-- UNION ALL keeps every row, always the correct choice hereتوافق أنواع الأعمدة
يجب أن يُنتج كل فرع من فروع UNION ALL العدد نفسه من الأعمدة، بأنواع متوافقة وبالترتيب نفسه. وتأتي أسماء الأعمدة من عبارة SELECT الأولى.
إذا اختلفت أنواع الأعمدة العريضة (مثلًا إذا كان أحدها int والآخر decimal)، فسيختار المحرك نوعًا مشتركًا. وإذا كانت الأنواع غير متوافقة فعلًا، فأجرِ تحويلًا صريحًا للنوع حتى لا تفشل عملية UNION.
SELECT region, 'revenue' AS metric, CAST(revenue AS decimal(12,2)) AS val FROM t
UNION ALL
SELECT region, 'units', CAST(units AS decimal(12,2)) FROM t;UNPIVOT في SQL Server
يحتوي SQL Server على عامل مخصص هو UNPIVOT، وهو أكثر إيجازًا من UNION ALL. فتحدّد اسم عمود القيمة الجديد، واسم عمود التسمية الجديد، ثم تسرد أعمدة المصدر التي تريد طيّها.
هناك سلوك مهم: يعمل UNPIVOT على حذف الصفوف التي تكون فيها القيمة NULL. ويختبر المحاوِرون ما إذا كنت تعرف هذا الأثر الجانبي.
SELECT region, quarter, amount
FROM wide_sales
UNPIVOT (
amount FOR quarter IN (q1, q2, q3, q4)
) AS u;يحذف UNPIVOT قيم NULL
إذا احتوت منطقة ما على NULL في q3، فإن UNPIVOT في SQL Server يحذف ذلك الصف ببساطة من الناتج. وإذا كنت تحتاج إلى صف لكل عمود بغض النظر عن قيم NULL، فارجع إلى UNION ALL، الذي يحافظ عليها.
اذكر هذه المفاضلة في المقابلة: إن UNPIVOT الأصلي موجز لكنه يفقد صفوف NULL، بينما UNION ALL مطوّل لكنه كامل.
-- UNPIVOT: q3 NULL for East -> no (East, Q3) row produced
-- UNION ALL: (East, 'Q3', NULL) row IS producedPostgreSQL: LATERAL VALUES
لا يحتوي PostgreSQL على UNPIVOT، لكن من الأساليب الأنيقة استخدام CROSS JOIN LATERAL على قائمة VALUES. إذ يُوسَّع كل صف عريض بمقابلته مع جدول مضمَّن صغير من أزواج (التسمية، القيمة).
وهذا أنظف من استخدام UNION ALL طويل، كما أنه يقرأ جدول المصدر مرة واحدة فقط.
SELECT w.region, v.quarter, v.amount
FROM wide_sales w
CROSS JOIN LATERAL (VALUES
('Q1', w.q1),
('Q2', w.q2),
('Q3', w.q3),
('Q4', w.q4)
) AS v(quarter, amount);قراءة الجدول مرة واحدة
من النقاط المتعلقة بالأداء التي يجدر ذكرها أن UNION ALL الساذج يفحص الجدول العريض مرة لكل فرع (أي أربع مرات لأربعة أرباع). أما صيغة LATERAL VALUES وUNPIVOT في SQL Server فتقرآن المصدر مرة واحدة.
يهم ذلك في الجداول الكبيرة. وإذا اضطررت إلى استخدام UNION ALL، فقد يظل المحسّن يفحص الجدول مرات متعددة، لذا اذكر أن LATERAL أو UNPIVOT خيار أكثر كفاءة.
تصفية الخلايا الفارغة
مع UNION ALL أو LATERAL، تحتفظ بصفوف القيم NULL. وإذا كان السؤال يتطلب الخلايا المعبّأة فقط، فأضف مرشحًا. وهذا يحاكي ما يفعله UNPIVOT في SQL Server تلقائيًا.
يُعد تحديد ما إذا كنت ستحتفظ بقيم NULL أو تحذفها قرارًا يعتمد على الحالة، لذا وضّح المتطلب مع المحاوِر قبل كتابة الشيفرة.
SELECT region, quarter, amount
FROM (
SELECT region, 'Q1' AS quarter, q1 AS amount FROM wide_sales
UNION ALL SELECT region, 'Q2', q2 FROM wide_sales
) t
WHERE amount IS NOT NULL;مثال تطبيقي: التجميع بعد Unpivot
متابعة شائعة: «من الجدول الربعي العريض، أعطني إجمالي الإيرادات لكل منطقة عبر جميع الأرباع». بعد تحويل البيانات إلى صيغة طويلة باستخدام Unpivot، يصبح التجميع بسيطًا: عملية SUM واحدة مجمّعة حسب المنطقة.
يوضح هذا السبب الحقيقي لاستخدام Unpivot أولًا. جمع أربعة أعمدة منفصلة عرضة للأخطاء، أما SUM(amount) GROUP BY region بصيغة طويلة فيتوسع ليتعامل مع أي عدد من الأرباع.
WITH long_sales AS (
SELECT region, 'Q1' AS quarter, q1 AS amount FROM wide_sales
UNION ALL SELECT region, 'Q2', q2 FROM wide_sales
UNION ALL SELECT region, 'Q3', q3 FROM wide_sales
UNION ALL SELECT region, 'Q4', q4 FROM wide_sales
)
SELECT region, SUM(amount) AS total
FROM long_sales
GROUP BY region;متى تستخدم Unpivot
تعرّف على مؤشر استخدام Unpivot في المسائل الوصفية:
- تحتوي المدخلات على أعمدة متكررة تمثل في الحقيقة قيمًا، مثل الأشهر والسنوات والمقاييس.
- تحتاج إلى إجراء تجميع أو ربط أو إنشاء مخطط عبر هذه القيم.
- تريد تطبيع بيانات جداول البيانات غير المطَبَّعة عند استيرادها.
تكون الصيغة الطويلة دائمًا تقريبًا هي البنية المناسبة لمواصلة العمل باستخدام SQL، لذلك يُعد Unpivot خطوة أولى شائعة.
تحقق سريع
تأكد من معرفتك بالمشكلة الأكثر شيوعًا في استخدام Unpivot.
مراجعة
يحوّل Unpivot الأعمدة إلى صفوف:
- قابل للنقل: عبارة
SELECTواحدة لكل عمود، مع ربطها باستخدامUNION ALL(وليس UNION العادي). - SQL Server: استخدام
UNPIVOTالأصلي، وهو موجز لكنه يحذف قيم NULL. - Postgres: استخدام
CROSS JOIN LATERAL (VALUES ...)، مع إجراء فحص واحد. - وحّد عدد الأعمدة وأنواعها بين الفروع، وصفِّ قيم NULL إذا كان السؤال يتطلب ذلك.
الأسئلة الشائعة
هل درس «تحويل الأعمدة إلى صفوف» مجاني؟
نعم — نص درس «تحويل الأعمدة إلى صفوف» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Coding Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة Coding Interview Prep 4 دروس في المجموع.
ماذا ستتعلم في «تحويل الأعمدة إلى صفوف»؟
عكس الجداول العريضة باستخدام UNPIVOT أو UNION ALL تتمرن على Coding Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Coding Interview Prep؟
لا تُشترط خبرة سابقة. Coding Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «تحويل الأعمدة إلى صفوف»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Coding Interview Prep هذا؟
نعم. كل درس في Coding Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إجراء Pivot باستخدام التجميع الشرطي
- صياغة PIVOT وCrosstab الخاصة بالمورّد
- تحويل الأعمدة إلى صفوف
- عمليات Pivot ديناميكية بأعمدة غير معروفة