Unpivoting data
  unpivoting data یک تکنیک بسیار کاربردی برای نرمال کردن جداولی است که به شکل غیر نرمال ایجاد شده اند. در واقع می شود گفت unpivoting عکس عمل pivoting می باشد.
   SQL Server
   ۵۰۴۰
   این مقاله حاوی فایل ضمیمه نمی باشد
   محمد سلیم آبادی
   ۱۳۸۹/۴/۱۰
ارسال لینک صفحه برای دوستان ارسال لینک صفحه برای دوستان  اضافه کردن به علاقه مندیها اضافه کردن به علاقه مندیها   نسخه قابل چاپ نسخه قابل چاپ

 

unpivoting data تکنیکی کاربردی و قابل استفاده برای نرمال سازی کردن (normalizing) جداول غیر نرمال (denormalized table) است.

هیچ چیزی بهتر از مثال نمی تواند مفاهیم را تفهیم کند. فرض کنید آمار تعداد پست های برخی از کاربران را در یک تالار گفتمان (forum) مشخص در سه ماه فروردین، اردیبهشت و خرداد سال 89 را می خواهیم در جدول ذخیره کنیم. داده ها به شکل before در جدول ذخیره شده اند و ما می خواهیم با query گرفتن از جدول before نتیجه ی after را بدست آوریم.

--============== before =====================
/*
user_name       Farvardin Ordibehesht Khordad
--------------- --------- ----------- -------
user_1          50        150         250
user_2          200       300         1200
user_3          0         0           900
*/

--============== after =====================
/*
user_name       Month       posts
--------------- ----------- --------------
user_1          Farvardin   50
user_1          Ordibehesht 150
user_1          Khordad     250
user_2          Farvardin   200
user_2          Ordibehesht 300
user_2          Khordad     1200
user_3          Farvardin   0
user_3          Ordibehesht 0
user_3          Khordad     900
*/

برای بدست آوردن این نتیجه از روشهای استاندارد زبان SQL دو روش شناخته شده وجود دارند. یکی استفاده از چندین union all و دیگری استفاده از جدول اعداد یا کپی کردن داده ها به تعداد ستون هایی که باید به سطر چرخش پیدا کنند. اگر هم از SQL Server 2005 و بالاتر استفاده می کنید می توانید از UNPIVOT برای حل این مساله استفاده کنید.

روش های مذکور به قرار زیر هستند:

--Declare Sample Table
DECLARE @sample TABLE
([user_namevarchar(15) NOT NULL UNIQUE,
 [Farvardin] tinyint NOT NULL DEFAULT(0),
 [Ordibehesht] tinyint NOT NULL DEFAULT(0),
 [Khordad] tinyint NOT NULL DEFAULT(0)) ;

--insert sample data
INSERT INTO @sample
VALUES ('user_1', 50, 150, 250),   
       ('user_2', 200, 300, 1200),  
       ('user_3', 0, 0, 900) ;  
       

--using number table method
SELECT [user_name], D.i AS [Month],
       CASE D.i WHEN 'Farvardin' THEN [Farvardin]
                WHEN 'Ordibehesht' THEN [Ordibehesht]
                WHEN 'Khordad' THEN [Khordad]
       END AS posts
FROM   @sample
       CROSS JOIN
       (SELECT 'Farvardin' UNION ALL
        SELECT 'Ordibehesht' UNION ALL
        SELECT 'Khordad') D(i) 

--using union all
SELECT [user_name], 'Farvardin' AS [Month], [Farvardin] AS [posts]
FROM   @sample
UNION ALL
SELECT [user_name], 'Ordibehesht', [Ordibehesht]
FROM   @sample
UNION ALL
SELECT [USER_NAME], 'Khordad', [Khordad]
FROM   @sample ;

--using UNPIVOT
SELECT *
FROM   @sample
UNPIVOT ([post] FOR [Month]
         IN (farvardin, ordibehesht, khordad)) AS U