SQL Server 2016:使用不同的迭代将多行转换为列

问题描述 投票:2回答:2

我有一个表,其中有许多InsuranceNo用于唯一的MemberID。如果有多个InsuranceNo,我希望InsuranceNo转移到一列,所以最后每个MemberID有一行,该ID的所有迭代都是一个列。

MemberID       InsuranceNo
--------------------------
123456            dser
124571            jklh
123456            abcd

我希望它看起来像这样:

MemberID       InsuranceNo1             InsuranceNo2
-----------------------------------------------------
123456            dser                  abcd
124571            jklh

谢谢!

sql sql-server sql-server-2016
2个回答
2
投票

还有一个选择......只需将“YourTable”更改为您的实际表名。

Declare @SQL varchar(max) = '
Select *
 From (
        Select MemberID
              ,Item     = concat(''InsuranceNo'',row_number() over (Partition By MemberID Order By (Select NULL)))
              ,Value    = InsuranceNo
         From YourTable
      ) A
 Pivot (max([Value]) For [Item] in (' + Stuff((Select ','+QuoteName(concat('InsuranceNo',ColNr)) 
                                               From (Select Distinct ColNr=row_number() over (Partition By MemberID Order By (Select NULL)) from YourTable ) A  
                                               For XML Path('')),1,1,'')  + ') ) p'
--Print @SQL
Exec(@SQL);

返回

MemberID    InsuranceNo1    InsuranceNo2
123456      dser            abcd
124571      jklh            NULL

如果它有助于围绕PIVOT,那么SQL Generated看起来像这样:

Select *
 From (
        Select MemberID
              ,Item     = concat('InsuranceNo',row_number() over (Partition By MemberID Order By (Select NULL)))
              ,Value    = InsuranceNo
         From YourTable
      ) A
 Pivot (max([Value]) For [Item] in ([InsuranceNo1],[InsuranceNo2]) ) p

1
投票

我更喜欢动态交叉选项卡到动态枢轴。我发现语法远不那么钝,如果你需要添加额外的列,这非常简单。这是我要解决的问题。当然,在您的情况下,您不需要临时表,因为您有一个实际的表要使用。

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something
(
    MemberID int
    , InsuranceNo varchar(10)
)

insert #Something values
(123456, 'dser')
, (124571, 'jklh')
, (123456, 'abcd')

declare @StaticPortion nvarchar(2000) = 
    'with OrderedResults as
    (
        select *, ROW_NUMBER() over(partition by MemberID order by InsuranceNo) as RowNum
        from #Something
    )
    select MemberID';

declare @DynamicPortion nvarchar(max) = '';
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by MemberID order by MemberID';

with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS 
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)

select @DynamicPortion = @DynamicPortion + 
    ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then InsuranceNo end) as InsuranceNo' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <= 
(
    select top 1 Count(*)
    from #Something
    group by MemberID
    order by COUNT(*) desc
)
select @StaticPortion + @DynamicPortion + @FinalStaticPortion

declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;
exec sp_executesql @SqlToExecute
© www.soinside.com 2019 - 2024. All rights reserved.