Sql 执行两级透视的存储过程

Sql 执行两级透视的存储过程,sql,pivot,sybase,sybase-asa,Sql,Pivot,Sybase,Sybase Asa,我正在尝试在Sybase Adaptive Server Anywhere中创建一个存储过程,它将执行表的双透视。我将首先用一些图片概述我试图完成的任务 问题 原始数据 这是表中的原始数据;在我下面发布的示例代码中,这是临时表t1: 第一级旋转 第一级数据透视涉及在列rownr上分组和在列col上数据透视,将结果表放入临时表t2中: 我有代码到这一点,我已经张贴在下面 第二级旋转 这是我正在努力解决的部分。我现在需要在列ObjectId上透视表t2分组,并复制列操作和分组中行数的代码以生成表t3

我正在尝试在Sybase Adaptive Server Anywhere中创建一个存储过程,它将执行表的双透视。我将首先用一些图片概述我试图完成的任务

问题

原始数据 这是表中的原始数据;在我下面发布的示例代码中,这是临时表t1:

第一级旋转 第一级数据透视涉及在列rownr上分组和在列col上数据透视,将结果表放入临时表t2中:

我有代码到这一点,我已经张贴在下面

第二级旋转 这是我正在努力解决的部分。我现在需要在列ObjectId上透视表t2分组,并复制列操作和分组中行数的代码以生成表t3。因此,我给出的示例的结果如下所示:

由于要复制两列操作和代码,因此结果表中的列数应等于2乘以具有最大行数的分组中的行数。小于最大分组行数的分组将用空值填充,如示例所示

代码

下面是我创建前两个表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解决此问题,因为它不像Sql Server那样具有pivot语句,因此使用pivot语句的解决方案对我没有帮助。

您需要在一个临时表中使用a、B等的每个集合及其ObjectID,并使用ObjectID的顺序整数1、2、3、4,不管op的字符串值是多少

对于一个恒等式,获得这样一个有序的整数通常很容易,但你不希望它是所有的,你希望它是每个A、B、C等子集

因此,如果可以在每个ObjectId值a、B、C等上运行一个游标,并将这些值的整数顺序操作放入临时表中,那么就可以轻松地使用多个外部联接进行透视

因此: 创建表盖数字8标识,op VARCHAR30,obj VARCHAR300 去

在ObjectId上获取一个光标并循环如下:

select  Id = IDENTITY(8)
    , t2.val op
    , t1.val obj
into 
existing table 
#l
from #t1 t1, #t1 t2
where t1.col = 'ObjectId'
and t1.val = 'A' -- this would be the cursors value
and t1.rownr = t2.rownr
and t2.col = 'Operation'
然后,您会发现,l可以很好地与多路外接器进行数据透视,因为您将有一个如下表:

select * from #l order by 3,1
 Id          op     obj  
 ----------- ------ -----
           1 Op1    A    
           2 Op2    A    
           1 Op3    B    
           2 Op4    B    
           3 Op5    B    

为了防止这对其他人有所帮助,以下是我最终提出的代码,以完成所需的双枢轴:

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
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