简体   繁体   English

有条件的Unpivot SQL表

[英]Conditional Unpivot SQL table

I have a table which looks like this <SubCodeReport3> which has a column called Rank . 我有一个看起来像这样的表<SubCodeReport3> ,其中有一个名为Rank的列。 For each row I need to the what is the Rank and based on that value I need to unpivot SubCode columns (SubCode1,SubCode2 & Subcode3 etc) and convert them into rows. 对于每一行,我需要什么是排名,并基于该值,我需要取消透视SubCode列(SubCode1,SubCode2和Subcode3等)并将其转换为行。

在此处输入图片说明

As seen above for a Rank 2 Subcode1 & SubCode2 have been unpivoted Rank 1 SubCode1 has been unpivoted Rank 3 Subcode1, Subcode2 & SubCode3 have been unpivoted. 如上所示,等级2的子代码1和子代码2已取消枢纽。等级1的子代码1已被取消枢纽。等级3子代码1,子代码2和SubCode3已取消枢纽。

there will not be case where the Rank is higher than the no. 排名不会高于排名。 of available SubCode columns. 可用的SubCode列。 Any Ideas? 有任何想法吗?

Cursor though rows ? 游标虽然行?

Here is some SQL to create this sample table 这是一些创建此示例表的SQL

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

Start with a CTE or derived table that does a full unpivot of the table, and adds a partitioned row_number so that for each row in the original table, SubCode1 will be on row_number 1, SubCode2 on row_number 2, etc. 从CTE或派生表开始,该表执行该表的完全取消操作,并添加一个分区的row_number,以便对于原始表中的每一行,SubCode1将位于row_number 1上,SubCode2将位于row_number 2上,等等。

Then select from that CTE where row_number is less than or equal to [Rank]. 然后从row_number小于或等于[Rank]的CTE中选择。

You need to CROSS JOIN to a table with sequential numbers: 您需要交叉联接到具有序号的表:

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

See Fiddle 小提琴

Since you know the number of subcodes you can always do this and your question asks how to 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 见小提琴

This is what worked for me. 这对我有用。

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM