列成行并创建列的主表

时间:2012-02-01 08:27:23

标签: sql-server tsql

我需要将列数据插入到不同的表中并为列创建主表

例如:我需要将表 tblcatData 转换为两个表 tblCat tblcatDataNew

tblCatData

    Primaykey | A | B | C | D | D | F | G | H | I | J | K | L | M |
--------------------------------------------------------------------
    1         | 1 | 2 | 3 | 5 | 5 | 5 | 3 | 3 | 3 | 1 | 4 | 1 | 1 |
    2         | 1 | 2 | 5 | 5 | 5 | 5 | 3 | 5 | 3 | 1 | 1 | 5 | 1 |
    3         | 5 | 2 | 3 | 5 | 5 | 5 | 5 | 3 | 3 | 1 | 1 | 1 | 4 |

tblCat

    PrimaryKey | Category
----------------------------
    1          | A
    2          | B
    3          | C
    4          | D
    5          | E
    6          | F
    7          | G
    .            .
    .            .
    .            .

tblCatDataNew

    PrimaryKey | FK_CatID | Data |
-----------------------------------
    1          | 1        | 1    |
    2          | 1        | 1    |
    3          | 1        | 5    |
    4          | 2        | 2    |
    5          | 2        | 2    |
    6          | 2        | 2    |
    7          | 3        | 3    |
    8          | 3        | 5    |
    .            .          .
    .            .          .
    .            .          .

2 个答案:

答案 0 :(得分:3)

您可以尝试以下方案:

  1. 创建tblCat

  2. 使用以下与原始设计的偏差创建tblCatDataNew

    • 允许FK_CatID列临时接受NULL(如果这是您的初衷,可能是永久性的);

    • 临时添加一个额外的列,以便从原始表中接收名称类别。

  3. 取消隐藏tblCatData并将结果插入tblCatDataNew(值为Data,列名称作为类别名称插入临时列。)

  4. tblCatDataNew中选择所有不同的类别名称,然后将其插入tblCat。 (这将为他们产生关键值。)

  5. tblCatDataNew更新tblCat中的外键,按类别名称加入两个表。

  6. tblCatDataNew删除临时列。

  7. tblCatDataNew.FK_CatID设为NOT NULL(也就是说,如果您希望如此)。

  8. 这是整个测试脚本,包括创建原始表(如果有人想尝试的话):

    BEGIN TRANSACTION
    GO
    
    /* prepare the original table, for tests */
    WITH data (
        Primaykey, A, B, C, D, E, F, G, H, I, J, K, L, M
    ) AS (
      SELECT 1   , 1, 2, 3, 5, 5, 5, 3, 3, 3, 1, 4, 1, 1 UNION ALL
      SELECT 2   , 1, 2, 5, 5, 5, 5, 3, 5, 3, 1, 1, 5, 1 UNION ALL
      SELECT 3   , 5, 2, 3, 5, 5, 5, 5, 3, 3, 1, 1, 1, 4
    )
    SELECT * INTO tblCatData FROM data;
    GO
    
    /* Step 1 */
    CREATE TABLE tblCat (
      PrimaryKey int IDENTITY CONSTRAINT PK_tblCat PRIMARY KEY,
      Category varchar(50) NOT NULL
    );
    GO
    
    /* Step 2 */
    CREATE TABLE tblCatDataNew (
      PrimaryKey int IDENTITY CONSTRAINT PK_tblCatDataNew PRIMARY KEY,
      FK_CatID int NULL CONSTRAINT FK_tblCatDataNew_tblCat FOREIGN KEY REFERENCES tblCat (PrimaryKey),
      Data int,
      Category varchar(50)
    );
    GO
    
    /* Step 3 */
    INSERT INTO tblCatDataNew (
      Data,
      Category
    )
    SELECT
      Data,
      Category
    FROM tblCatData
    UNPIVOT (
      Data for Category IN (A, B, C, D, E, F, G, H, I, J, K, L, M)
    ) u
    ORDER BY
      Category,
      Primaykey;
    GO
    
    /* Step 4 */
    INSERT INTO tblCat (Category)
    SELECT DISTINCT Category
    FROM tblCatDataNew
    GO
    
    /* Step 5 */
    UPDATE tblCatDataNew
    SET FK_CatID = c.PrimaryKey
    FROM tblCat c
    WHERE tblCatDataNew.Category = c.Category
    
    GO
    
    /* Step 6 */
    ALTER TABLE tblCatDataNew
    DROP COLUMN Category
    GO
    
    /* Step 7 */
    ALTER TABLE tblCatDataNew
    ALTER COLUMN FK_CatID int NOT NULL
    GO
    
    /* view the results */
    SELECT * FROM tblCat
    SELECT * FROM tblCatDataNew
    GO
    
    ROLLBACK TRANSACTION
    

    请注意,从2005版开始,SQL Server支持UNPIVOT子句。在早期版本中,您必须使用不同的方法来取消数据的显示(步骤3),例如,像这样:

    INSERT INTO tblCatDataNew (
      Data,
      Category
    )
    SELECT
      Data = CASE x.CatNum
        WHEN  1 THEN A
        WHEN  2 THEN B
        WHEN  3 THEN C
        WHEN  4 THEN D
        WHEN  5 THEN E
        WHEN  6 THEN F
        WHEN  7 THEN G
        WHEN  8 THEN H
        WHEN  9 THEN I
        WHEN 10 THEN J
        WHEN 11 THEN K
        WHEN 12 THEN L
        WHEN 13 THEN M
      END,
      Category = CASE x.CatNum
        WHEN  1 THEN 'A'
        WHEN  2 THEN 'B'
        WHEN  3 THEN 'C'
        WHEN  4 THEN 'D'
        WHEN  5 THEN 'E'
        WHEN  6 THEN 'F'
        WHEN  7 THEN 'G'
        WHEN  8 THEN 'H'
        WHEN  9 THEN 'I'
        WHEN 10 THEN 'J'
        WHEN 11 THEN 'K'
        WHEN 12 THEN 'L'
        WHEN 13 THEN 'M'
      END
    FROM tblCatData
      CROSS JOIN (
        SELECT  1 UNION ALL
        SELECT  2 UNION ALL
        SELECT  3 UNION ALL
        SELECT  4 UNION ALL
        SELECT  5 UNION ALL
        SELECT  6 UNION ALL
        SELECT  7 UNION ALL
        SELECT  8 UNION ALL
        SELECT  9 UNION ALL
        SELECT 10 UNION ALL
        SELECT 11 UNION ALL
        SELECT 12 UNION ALL
        SELECT 13
      ) x (CatNum)
    ORDER BY
      Category,
      Primaykey;
    

    甚至是这样:

    INSERT INTO tblCatDataNew (
      Data,
      Category
    )
    SELECT
      Data = CASE x.CatNum
        WHEN  1 THEN A
        WHEN  2 THEN B
        WHEN  3 THEN C
        WHEN  4 THEN D
        WHEN  5 THEN E
        WHEN  6 THEN F
        WHEN  7 THEN G
        WHEN  8 THEN H
        WHEN  9 THEN I
        WHEN 10 THEN J
        WHEN 11 THEN K
        WHEN 12 THEN L
        WHEN 13 THEN M
      END,
      Category = x.CatName
    FROM tblCatData
      CROSS JOIN (
        SELECT  1, 'A' UNION ALL
        SELECT  2, 'B' UNION ALL
        SELECT  3, 'C' UNION ALL
        SELECT  4, 'D' UNION ALL
        SELECT  5, 'E' UNION ALL
        SELECT  6, 'F' UNION ALL
        SELECT  7, 'G' UNION ALL
        SELECT  8, 'H' UNION ALL
        SELECT  9, 'I' UNION ALL
        SELECT 10, 'J' UNION ALL
        SELECT 11, 'K' UNION ALL
        SELECT 12, 'L' UNION ALL
        SELECT 13, 'M'
      ) x (CatNum, CatName)
    ORDER BY
      Category,
      Primaykey;
    

    以上脚本为我生成的结果如下:

    • tblCat

      PrimaryKey  Category
      ----------- --------------------------------------------------
      1           A
      2           B
      3           C
      4           D
      5           E
      6           F
      7           G
      8           H
      9           I
      10          J
      11          K
      12          L
      13          M
      
    • tblCatDataNew

      PrimaryKey  FK_CatID    Data
      ----------- ----------- -----------
      1           1           1
      2           1           1
      3           1           5
      4           2           2
      5           2           2
      6           2           2
      7           3           3
      8           3           5
      9           3           3
      10          4           5
      11          4           5
      12          4           5
      13          5           5
      14          5           5
      15          5           5
      16          6           5
      17          6           5
      18          6           5
      19          7           3
      20          7           3
      21          7           5
      22          8           3
      23          8           5
      24          8           3
      25          9           3
      26          9           3
      27          9           3
      28          10          1
      29          10          1
      30          10          1
      31          11          4
      32          11          1
      33          11          1
      34          12          1
      35          12          5
      36          12          1
      37          13          1
      38          13          1
      39          13          4
      

答案 1 :(得分:0)

您可以使用union取消删除列,并select ... into将结果存储在新表中:

select  PrimaryKey
,       FK_CatId
,       Category
into    tblCatDataNew
from    (
        select  PrimaryKey
        ,       1
        ,       A
        from    tblCatData
        union all
        select  PrimaryKey
        ,       2
        ,       B
        from    tblCatData
        union all
        ...
        )