SQL 事务、动态 SQL、条件透视

问题描述 投票:0回答:1

我正在尝试将垂直数据集转换为水平数据集。当前数据集列出了一个唯一的 id(VARCHAR),该 id 在数据集中最多可能出现 (13) 次。每个 id 行包含 (1) c_id 值、(1) op 值、(1) 得分值、(1) sp_id 值以及该 c_id 独有的附加值以及一些常见值,例如 p。只有两个值不能为空 id 和 c_id。 op 值可以跨 id 行求和到 100,并且是对数据准确性的编辑检查。

   DECLARE @Table1 TABLE
        (
          id VARCHAR(1) NOT NULL
         ,c_id INT NOT NULL
         ,op FLOAT NULL
         ,score FLOAT NULL
         ,sp_id INT NULL     
         ,p VARCHAR(2) NULL
        ) 
        INSERT INTO @Table1 
        (id, c_id, op, score, sp_id, p)
    VALUES ('1', '1', '51', '4','2','a')
          ,('1', '2', NULL, '3','1',NULL)
          ,('1', '3','20', '4',NULL,'a')
          ,('1', '4', '20', '4','5','a')
          ,('1', '5', '9', '4','4','a')
          ,('2', '6','100', NULL, NULL,NULL)
          ,('3', '7','100','4',NULL,'a')
          ;

数据是这样的

id c_Id op 分数 sp_id p
1 1 51 4 2 a
1 2 3 1
1 3 20 4 a
1 4 20 4 5 a
1 5 9 4 4 a
2 6 100
3 7 100 4 a

我提供的示例数据有 7 行,我想将其转换为 (3) 行,每个唯一 id 一行。第 1 行输出将具有 (4) 个 c_id 值,即使原始数据集具有 (5) 个 c_id 值。当 op 为 null 或 = 0 时,我们不会为该 c_id 创建新列,但会捕获分数。如果 sp_id 值为 NULL,则 cpid_score 也将为 NULL。

            DECLARE @Table2 TABLE
        (  p VARCHAR (2) NULL
          ,sum_op INT NULL
          ,id VARCHAR(1) NOT NULL         
          ,cid1 INT NULL
          ,op1 FLOAT NULL
          ,cid1_score FLOAT NULL
          ,spid1 INT NULL
          ,spid1_score FLOAT NULL       
          ,cid2 INT NULL
          ,op2 FLOAT NULL
          ,cid2_score FLOAT NULL
          ,spid2 INT NULL   
          ,spid2_score FLOAT NULL     
          ,cid3 INT NULL
          ,op3 FLOAT NULL
          ,cid3_score FLOAT NULL
          ,spid3 INT NULL   
          ,spid3_score FLOAT NULL     
          ,cid4 INT NULL
          ,op4 FLOAT NULL
          ,cid4_score FLOAT NULL
          ,spid4 INT NULL
          ,spid4_score FLOAT NULL
        ) 
    
    INSERT INTO @Table2
        (  p,sum_op ,id,cid1,op1,cid1_score,spid1,spid1_score,cid2,op2,cid2_score,spid2,spid2_score,cid3,op3,cId3_score,spid3,spid3_score,cid4,op4,cid4_score,spid4,spid4_score)
    VALUES ('a','100','1','1','51','4','2','3','3','20','4',NULL,NULL,'4','20','4','5',NULL,'5','9','4','4',NULL),
           (NULL,'100','2','6',NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
           ('a','100','3','7','4', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL,NULL, NULL, NULL, NULL,NULL, NULL, NULL)
          ;

切换到动态sql,因为我不知道随着时间的推移,每个id会关联多少个cid。不知道如何迭代 _ 1 , _ 2.... 值

    DECLARE @columns NVARCHAR(MAX);
    DECLARE @sql NVARCHAR(MAX);
    
    -- Generate the dynamic column list based on cid values, how do I add  underscore and iterative #
    SELECT @columns = COALESCE(@columns + ', ', '') + CAST(cid AS VARCHAR)
    FROM (
      SELECT DISTINCT cid
      FROM table1
    ) AS Contacts;
    
    -- Build the dynamic SQL statement
    SET @sql = N'
    SELECT id, ' + @columns + ', op, score, spid
    FROM (
      SELECT id, 
             CAST(ROW_NUMBER() OVER (PARTITION BY id ORDER BY contact_id) AS VARCHAR) AS cid_column,
             cid, op, score, spid
      FROM table1
    ) AS SourceTable
    PIVOT (
      MAX(cid)
      FOR cid IN (' + @columns + ')
    ) AS PivotTable
    ORDER BY id;
    ';
    
    -- Execute the dynamic SQL statement
    EXEC sp_executesql @sql;


sql pivot pivot-table case
1个回答
0
投票

你的问题不清楚。 首先,尝试根据条件将您的数据转换为

id 第N行 c_id op c_分数 sp_id sp_分数 p
1 1 1 51 4 2 3 a
1 2 3 20 4 a
1 3 4 20 4 5 a
1 4 5 9 4 4 a

然后旋转到所需的形状。

数据透视操作是 DBMS 特定的。您使用什么数据库管理系统?

© www.soinside.com 2019 - 2024. All rights reserved.