从非规范化 table 加载规范化 table

Loading a normalized table from a denormalized table

我有一个 table 结构,如下所示:

ID|Letter1|Letter2|Letter3|...n
-------------------------------
1    A       C       NULL  ...

2    A       D       D

3    P       F       M

使用 select 我必须将其加载到更规范化的 table 中,例如:

ID|Letter|
1    A
1    C
1    NULL
1    ...
2    A
2    D
2    D
3    P
3    F
3    M

我尝试过不同的方法:

INSERT INTO Normalized
 (ID, Letter)
SELECT ID, LETTER1
FROM Denormalized

并且对字母的每次迭代都一遍又一遍地这样做。我的问题是,我有超过 100 个这种糟糕设计的字母字段,我试图围绕不同的想法思考,但没有任何结果。

我的问题是有没有人知道一种动态的方法来将每个字母从非规范化的 table 插入到规范化的 table 中,同时为每个字母创建不同的行?

Declare @XML xml = (Select * from Denormalized for XML RAW)

INSERT INTO Normalized
Select ID     = r.value('@ID','int')
      --,Item   = attr.value('local-name(.)','varchar(100)')  -- Removed but will return Field Name
      ,Letter  = attr.value('.','varchar(max)') 
 From  @XML.nodes('/row') as A(r)
 Cross Apply A.r.nodes('./@*') AS B(attr)
 Where attr.value('local-name(.)','varchar(100)') not in ('ID')

Returns(带 XML 的动态版本省略 NULLS)

ID  Letter
1   A
1   B
2   A
2   D
2   D
3   P
3   F
3   M

EDIT - To Keep the NULLS, another option is to use a CROSS APPLY

INSERT INTO Normalized
Select A.ID
      ,B.Letter
 From  Denormalized A
 Cross Apply (Values 
              (A.Letter1)
             ,(A.Letter2)
             ,(A.Letter3)
             --...
             --,(A.LetterN)
             ) B (Letter)

Returns

ID  Letter
1   A
1   B
1   NULL   << We kept the NULL
2   A
2   D
2   D
3   P
3   F
3   M