البرمجة

تحويل أعمدة إلى صفوف في SQL Server

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

sql
-- إنشاء جدول وهمي يحتوي على أعداد تسلسلية من 1 إلى العدد الذي تحتاجه WITH Numbers AS ( SELECT 1 AS Number UNION ALL SELECT Number + 1 FROM Numbers WHERE Number < (SELECT Count FROM YourTable WHERE ID = 1) -- استبدال YourTable بإسم جدولك الأصلي ), -- الجدول النهائي بعد الدمج FinalTable AS ( SELECT ID, DATEADD(MONTH, Number - 1, [Start Dt]) AS [Start Dt], DATEADD(MONTH, Number, [Start Dt]) AS [End Dt], 1 AS [Count] -- 1 لأن كل صف يحتوي على قيمة 1 FROM Numbers JOIN YourTable ON ID = 1 -- استبدال YourTable بإسم جدولك الأصلي و 1 بالقيمة المناسبة لـ ID ) -- استعلام نهائي لاسترداد النتيجة SELECT ID, [Start Dt], [End Dt], [Count] FROM FinalTable ORDER BY [Start Dt] OPTION (MAXRECURSION 0); -- السماح بالتكرار غير المحدود في الجدول الوهمي

هذا الاستعلام يعتمد على استخدام CTE (Common Table Expression) لإنشاء جدول وهمي يحتوي على الأعداد التسلسلية اللازمة، ثم يقوم بدمجه مع الجدول الأصلي لإنشاء الصفوف المطلوبة. يرجى استبدال YourTable بالاسم الصحيح لجدولك وضبط الشرط في CTE ليتناسب مع القيمة الفعلية لعمود Count التي تريد استخدامها.

المزيد من المعلومات

يمكن تحسين الحل باستخدام وظيفة متقدمة في SQL Server تُسمى ROW_NUMBER()، التي تُستخدم لإنشاء أعداد متسلسلة للصفوف. باستخدام هذه الوظيفة، يمكننا تقسيم فترة الزمنية إلى فترات فرعية بحيث يتم توليد صف لكل فترة فرعية. اليك الاستعلام المحسن:

sql
WITH NumberedDates AS ( SELECT ID, [Start Dt], [End Dt], [Count], ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [Start Dt]) AS RowNum FROM YourTable ), -- استخدام CROSS APPLY لتوليد الصفوف RecursiveTable AS ( SELECT ID, [Start Dt], DATEADD(MONTH, 1, [Start Dt]) AS [End Dt], 1 AS [Count] FROM NumberedDates WHERE RowNum = 1 UNION ALL SELECT d.ID, DATEADD(MONTH, r.RowNum, d.[Start Dt]) AS [Start Dt], DATEADD(MONTH, r.RowNum + 1, d.[Start Dt]) AS [End Dt], 1 AS [Count] FROM NumberedDates d JOIN RecursiveTable r ON d.ID = r.ID AND r.RowNum < d.[Count] ) SELECT ID, [Start Dt], [End Dt], [Count] FROM RecursiveTable ORDER BY [Start Dt];

هذا الاستعلام يستخدم ROW_NUMBER() لترقيم الصفوف في كل مجموعة (PARTITION BY ID) بناءً على الترتيب الزمني. ثم يستخدم CROSS APPLY مع جدول وهمي يتم إنشاؤه باستخدام UNION ALL لتوليد الصفوف الفرعية بناءً على الأعداد التسلسلية.

زر الذهاب إلى الأعلى