2

私はSQLにかなり慣れていないので、これを理解しようとしています:

その年の各月に 12 の列があり、その月の予算残高を表示する BUDGET というテーブルがあります。したがって、テーブルは次のようになります。

[Department]  [Year]  [Month1] [Month2] .... [Month12]  
ABCD           2010   $5000     $5500   .....  $4000
ABCD           2011   $6000     $6500   .....  $3000

私がやろうとしているのは、このテーブルを正規化し、各行を次の形式の日付フィールドを持つ 12 行に分割することです。また、その月の値を表示する [Balance] 列も必要です。したがって、正規化されたテーブルは次のようになります。

[Department]  [Date]     [Balance] 
ABCD          20100101     $5000   
ABCD          20100201     $5500 
ABCD          20100301     .....
ABCD          .......      ......

同じテーブルで CROSS JOIN を使用しようとしましたが、失敗しました。while ループも使用しようとしましたが、それも失敗しました。どんな種類の助けも大歓迎です。ありがとう!

編集: SQL Server 2008 を使用しています

4

3 に答える 3

10

楽しみのために、ここにCROSSAPPLYソリューションがあります。

SELECT
   B.Department,
   DateAdd(month, (B.Year - 1900) * 12 + M.Mo - 1, 0) [Date],
   M.Balance
FROM
   dbo.Budget B
   CROSS APPLY (
      VALUES
      (1, Month1), (2, Month2), (3, Month3), (4, Month4), (5, Month5), (6, Month6),
      (7, Month7), (8, Month8), (9, Month9), (10, Month10), (11, Month11), (12, Month12)
   ) M (Mo, Balance);

UNPIVOTを使用しない限り、@AaronBertrandのUNPIVOTとまったく同じです。

日付を文字列として指定する必要がある場合は、文字列をCROSS APPLYのように配置('01', Month1)し、SELECTをに変更しConvert(char(4), B.Year) + M.Moます。

于 2012-08-07T01:29:07.090 に答える
4
SELECT 
  Department, 
  [Date] = DATEADD(MONTH, CONVERT(INT, SUBSTRING([Month],6,2))-1, 
     DATEADD(YEAR, [Year]-1900, 0)), 
  Balance
FROM
  dbo.BUDGET AS b
  UNPIVOT 
  (
    Balance FOR [Month] IN 
    (
      Month1, Month2,  Month3,  Month4,
      Month5, Month6,  Month7,  Month8,
      Month9, Month10, Month11, Month12
    )
  ) AS y
ORDER BY Department, [Date];
于 2012-08-07T01:10:56.483 に答える
1

これが私のやり方です。それについてすべての空想を得る必要はありません。

select department = b.department ,
       year       = b.year       ,
       month      = m.month      ,
       balance    = case m.month
                    when  1 then b.Month1
                    when  2 then b.Month2
                    when  3 then b.Month3
                    when  4 then b.Month4
                    when  5 then b.Month5
                    when  6 then b.Month6
                    when  7 then b.Month7
                    when  8 then b.Month8
                    when  9 then b.Month9
                    when 10 then b.Month10
                    when 11 then b.Month11
                    when 12 then b.Month12
                    else         null
                    end
from dbo.budget b
join (           select month =  1
       union all select month =  2
       union all select month =  3
       union all select month =  4
       union all select month =  5
       union all select month =  6
       union all select month =  7
       union all select month =  8
       union all select month =  9
       union all select month = 10
       union all select month = 11
       union all select month = 12
     ) m on 1 = 1  -- a dummy join: we want the cartesian product here so as to expand every row in budget into twelve, one per month of the year.
于 2012-08-07T01:22:14.733 に答える