[英]Stored procedure to do a two-level pivot
我正在嘗試在Sybase
Adaptive Server Anywhere
中創建一個存儲過程,該存儲過程將完成表的雙重操作。 我將首先用一些圖像概述我要完成的工作。
問題
這是表中的原始數據; 在我下面向下發布的示例代碼中,這是臨時表#t1:
數據rownr
的第一級包括對rownr
列進行分組和對列col
rownr
,將結果表放入臨時表#t2中:
到目前為止,我已經發布了下面的代碼。
這是我正在努力的部分。 現在,我需要對ObjectId
列上的表#t2分組進行透視,並為該分組中的行數復制列Operation
和Code
,以生成表#t3。 因此,我給出的示例的結果將如下所示:
因為要復制兩列(“ Operation
和Code
),所以結果表中的列數應等於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
不具有一個pivot
聲明像Sql Server
呢,所以使用的解決方案pivot
聲明絕不會幫我。
您需要在單個臨時表中的每組A,B等及其ObjectId,對ObjectID的排序整數為1,2,3,4,而與op的字符串值無關。
有了IDENTITY,獲得這樣一個有序整數通常很容易,但是您並不想全部都想要它,而是希望每個A,B,C等子集都需要它。
因此,如果您可以對每個ObjectId值(A,B,C等)運行Cursor並將這些對象的整數排序操作放入臨時表中,則可以輕松進行多個外部聯接的數據透視。
所以:創建表#l(Id NUMERIC(8)IDENTITY,op VARCHAR(30),obj VARCHAR(300))去
set identity_insert #l on
在objectIds上獲取一個游標,然后像這樣循環:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.