条件逆轴 SQL table

Conditional Unpivot SQL table

我有一个 table,看起来像这样 <SubCodeReport3>,它有一个名为 Rank 的列。对于每一行,我需要什么是排名,并根据该值我需要取消透视 SubCode 列(SubCode1、SubCode2 和 Subcode3 等)并将它们转换为行。

如上所示 Rank 2 Subcode1 & SubCode2 已被取消透视 等级 1 SubCode1 已被取消透视 等级 3 Subcode1、Subcode2 和 SubCode3 已取消透视。

不会出现Rank高于no的情况。可用的 SubCode 列。有任何想法吗?

光标遍历行?

这里有一些 SQL 来创建这个示例 table

    USE TESTDB
GO
/****** Object:  Table [dbo].[SubCodeReport3]    Script Date: 10/6/2015 2:27:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[SubCodeReport3](
    [ S-ID] [varchar](50) NULL,
    [Rank] [smallint] NULL,
    [AGE] [varchar](50) NULL,
    [SchoolCode] [varchar](50) NULL,
    [SubCode1] [varchar](50) NULL,
    [SubCode2] [varchar](50) NULL,
    [SubCode3] [varchar](50) NULL,
    [SubCode4] [varchar](50) NULL,
    [SubCode5] [varchar](50) NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'25', 1, N'23', N'KEN-009', N'ENG', N'MAT', N'ZOO', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'26', 1, N'21', N'DLK-009', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'27', 2, N'25', N'DLK-006', N'MAT', N'ENG', N'STAT', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'28', 1, N'21', N'HLI-005', N'ENG', N'', N'', N'', N'')
INSERT [dbo].[SubCodeReport3] ([ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]) VALUES (N'30', 3, N'22', N'INN-009', N'ENG', N'MAT', N'ZOO', N'GEO', N'')

从 CTE 或派生的 table 开始,对 table 进行完整的逆轴旋转,然后添加分区的 row_number,以便对于原始 [=19= 中的每一行], SubCode1 将在 row_number 1 上,SubCode2 将在 row_number 2 上,等等

然后 select 来自 row_number 小于或等于 [Rank] 的 CTE。

您需要 CROSS JOIN 到 table 序列号:

with cte as
 (
  select 1 as n 
  union all select 2 
  union all select 3
  union all select 4
  union all select 5
 )
select Rank, Age, SchoolCode, 
   case n
      when 1 then SubCode1 
      when 2 then SubCode2 
      when 3 then SubCode3 
      when 4 then SubCode4 
      when 5 then SubCode5 
   end as SubCode
from SubCodeReport3
join cte 
  on n <= rank

Fiddle

既然你知道子代码的数量,你总是可以这样做,你的问题是如何 UNPIVOT:

select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
  from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1]
          from SubCodeReport3 SCR3
         where SCR3.[Rank] = 1) R1
         unpivot (SubCode FOR Subject IN (SubCode1)) as unpvt1
UNION ALL         
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
  from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2]
          from SubCodeReport3 SCR3
         where SCR3.[Rank] = 2) R1
         unpivot (SubCode FOR Subject IN (SubCode1, SubCode2)) as unpvt2         
UNION ALL         
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
  from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3]
          from SubCodeReport3 SCR3
         where SCR3.[Rank] = 3) R1
         unpivot (SubCode FOR Subject IN (SubCode1, SubCode2, SubCode3)) as unpvt3
UNION ALL         
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
  from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4]
          from SubCodeReport3 SCR3
         where SCR3.[Rank] = 4) R1
         unpivot (SubCode FOR Subject IN (SubCode1, SubCode2, SubCode3, SubCode4)) as unpvt4
UNION ALL         
select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode]
  from (select [ S-ID], [Rank], [AGE], [SchoolCode], [SubCode1], [SubCode2], [SubCode3], [SubCode4], [SubCode5]
          from SubCodeReport3 SCR3
         where SCR3.[Rank] = 5) R1
         unpivot (SubCode FOR Subject IN (SubCode1, SubCode2, SubCode3, SubCode4, SubCode5)) as unpvt5

See fiddle

这对我有用。

WITH CodesReportCTE 
(
       [Number]
      ,[ S-ID]
      ,[Rank]
      ,[AGE]
      ,[SchoolCode]
      ,[Code]
)
AS
(

SELECT 
       ROW_NUMBER() over (PARTITION BY [ S-ID],[SchoolCode] ORDER BY [ S-ID],[SchoolCode]) AS Number
      ,[ S-ID]
      ,[Rank]
      ,[AGE]
      ,[SchoolCode]
      ,up.Code [Code]
  FROM [dbo].[SubCodeReport3]
  UNPIVOT
  (
  Code
  for x in (SubCode1,SubCode2,SubCode3,SubCode4,SubCode5) ) up
  WHERE up.Code <> ' '

)

SELECT 
       --[Number]
      --,
      [ S-ID]
      ,[Rank]
      ,[AGE]
      ,[SchoolCode]
      ,[Code]

      FROM CodesReportCTE
      WHERE Number <= [Rank]