存储过程执行两级透视

时间:2015-06-30 11:14:00

标签: sql pivot sybase sybase-asa

我正在尝试在Sybase Adaptive Server Anywhere中创建一个存储过程,该存储过程将执行表的双重轴。我将首先概述一些我想要完成的图像。

问题

  1. 原始数据
  2. 这是表格中的原始数据;在我发布的示例代码中,这是临时表#t1:

    enter image description here

    1. 第一级旋转
    2. 第一级透视涉及对列rownr进行分组并在列col上进行旋转,将结果表放入临时表#t2:

      enter image description here

      到目前为止,我已经将代码发布到了低位。

      1. 第二级转动
      2. 这是我正在努力的部分。我现在需要在列ObjectId上转移表#t2分组并复制列OperationCode以获取分组中的行数以生成表#t3。所以我给出的例子的结果看起来像这样:

        enter image description here

        由于正在复制两列(OperationCode),因此结果表中的列数应等于2乘以具有最大行数的分组中的行数。 less 小于最大分组行数的分组将使用空值填充,如示例所示。

        代码

        这是我创建前两个表的代码,#t1和#t2:

        begin
            create table #t1(rownr int, col nvarchar(15), val nvarchar(300));
            insert into #t1 values(1, 'ObjectId', 'A');
            insert into #t1 values(1, 'Operation', 'Op1');
            insert into #t1 values(1, 'Code', '101');
            insert into #t1 values(2, 'ObjectId', 'A');
            insert into #t1 values(2, 'Operation', 'Op2');
            insert into #t1 values(2, 'Code', '102');
            insert into #t1 values(3, 'ObjectId', 'B');
            insert into #t1 values(3, 'Operation', 'Op3');
            insert into #t1 values(3, 'Code', '103');
            insert into #t1 values(4, 'ObjectId', 'B');
            insert into #t1 values(4, 'Operation', 'Op4');
            insert into #t1 values(4, 'Code', '104');
            insert into #t1 values(5, 'ObjectId', 'B');
            insert into #t1 values(5, 'Operation', 'Op5');
            insert into #t1 values(5, 'Code', '105');
            -- Create t2
            select 
                rownr,
                Max(case when col = 'ObjectId' then val end) as ObjectId,
                Max(case when col = 'Operation' then val end) as Operation,
                Max(case when col = 'Code' then val end) as Code
                into #t2
            from #t1
            group by rownr
            order by rownr, ObjectId;
            select * from #t2; 
            -- Create #t3    <--- This is where I need help
        end
        

        请注意

        请注意,我正在尝试为Sybase Adaptive Server Anywhere解决此问题,pivot语句,如Sql Server那样,所以使用pivot语句的解决方案对我没有帮助。

2 个答案:

答案 0 :(得分:0)

您需要在具有ObjectIds的单个临时表中使用每组A,B等,对ObjectIDs使用排序整数1,2,3,4,而不管op的字符串值。

使用IDENTITY获取这样的有序整数通常很容易,但是你并不想要它,你需要每个A,B,C等子集。

因此,如果你可以在每个ObjectId值(A,B,C等)上运行Cursor并获取那些进入临时表的整数排序操作,那么你可以轻松地使用多个外连接进行数据转换。

所以:     create table #l(Id NUMERIC(8)IDENTITY,op VARCHAR(30),obj VARCHAR(300))     去

git reset --hard && git clean -dfx

获取objectIds上的光标并循环:

alias gpristine='git reset --hard && git clean -dfx'

然后你会发现#l可以很好地与多用途outers一起转动,因为你会有一个像这样的表:

set identity_insert #l on

答案 1 :(得分:0)

以防万一这有助于其他人,这里是我最终想出来完成所需双重支点的代码:

begin
    DECLARE @nr_of_columns smallint;
    DECLARE @qry long varchar;
    DECLARE @i SMALLINT;
    DECLARE @createTable nvarchar(1000);
    create table #t1(rownr int, col nvarchar(15), val nvarchar(300));
    insert into #t1 values(1, 'ObjectId', 'A');
    insert into #t1 values(1, 'Operation', 'Op1');
    insert into #t1 values(1, 'Code', '101');
    insert into #t1 values(2, 'ObjectId', 'A');
    insert into #t1 values(2, 'Operation', 'Op2');
    insert into #t1 values(2, 'Code', '102');
    insert into #t1 values(3, 'ObjectId', 'B');
    insert into #t1 values(3, 'Operation', 'Op3');
    insert into #t1 values(3, 'Code', '103');
    insert into #t1 values(4, 'ObjectId', 'B');
    insert into #t1 values(4, 'Operation', 'Op4');
    insert into #t1 values(4, 'Code', '104');
    insert into #t1 values(5, 'ObjectId', 'B');
    insert into #t1 values(5, 'Operation', 'Op5');
    insert into #t1 values(5, 'Code', '105');
    -- create t2
    select 
        rownr,
        Max(case when col = 'ObjectId' then val end) as ObjectId,
        Max(case when col = 'Operation' then val end) as Operation,
        Max(case when col = 'Code' then val end) as Code
        into #t2
    from #t1
    group by rownr
    order by rownr, ObjectId;
    -- create #t3
  -- Maximum number of column groups in result table
  select max(cols) into @nr_of_columns from (SELECT count() over (partition by ObjectId) as cols from #t2) A;
  -- Create temporary table #t3 to hold results
  SET @i = 1;
  SET @createTable = 'create table #t3(ObjectId nvarchar(300)';
  while @i <= @nr_of_columns loop
    set @createTable = @createTable || ', Operation' || @i || ' nvarchar(300), Code' || @i || ' nvarchar(300)';
    set @i = @i + 1;
  end loop;
  set @createTable = @createTable || ')';
  execute immediate (@createTable);
  -- Pivot into #t3
  for whatever as cur cursor for 
    select 'insert into #t3 select ' || rw as qry from 
    (select '''' || A.ObjectId || ''' AS ObjectId, ' || LIST(attributes) || repeat(',null,null', @nr_of_columns-A.nr_in_group) AS rw from
     (SELECT ObjectId, count() over (partition by ObjectId) nr_in_group, row_number() over (partition by ObjectId order by Operation) nr, ''''||Operation||''' AS Operation' || nr || ',' || '''' || Code || ''' AS Code' || nr  as attributes FROM #t2 order by ObjectId,Operation) A
     group by ObjectId,@nr_of_columns, nr_in_group) B
   DO 
     execute IMMEDIATE (qry);
   end for;
  -- Output #t2
  select * from #t3;
end