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