Sql server 如何使数据行成为分组列?

Sql server 如何使数据行成为分组列?,sql-server,Sql Server,我想按ID分组,但要让每个列组显示为一组新的水平列 我有一个这样的数据表 ╔════╦═══════╦════════╗ ║ ID ║ Phone ║ Type ║ ╠════╬═══════╬════════╣ ║ A ║ 111 ║ home ║ ║ A ║ 222 ║ work ║ ║ B ║ 333 ║ cell ║ ║ B ║ 444 ║ school ║ ╚════╩═══════╩════════╝ 我想让它看起来像 ╔════╦═════

我想按ID分组,但要让每个列组显示为一组新的水平列

我有一个这样的数据表

╔════╦═══════╦════════╗
║ ID ║ Phone ║  Type  ║
╠════╬═══════╬════════╣
║  A ║   111 ║ home   ║
║  A ║   222 ║ work   ║
║  B ║   333 ║ cell   ║
║  B ║   444 ║ school ║
╚════╩═══════╩════════╝
我想让它看起来像

╔════╦════════╦═══════╦════════╦════════╗
║ ID ║ Phone1 ║ Type1 ║ Phone2 ║ Type2  ║
╠════╬════════╬═══════╬════════╬════════╣
║  A ║    111 ║ home  ║    222 ║ work   ║
║  B ║    333 ║ cell  ║    444 ║ school ║
╚════╩════════╩═══════╩════════╩════════╝
理想情况下,我会找到一个解决方案,可以处理任意数量的重复组,但如果有必要,我可以硬编码这个数字

我可以拥有多达100000个唯一ID,其中包含20个重复的列组集,每个列组最多包含5个单独的列

看起来PIVOT会有帮助,但我不知道怎么做

编辑:这里要非常清楚,我不希望行数据成为列标题。我希望当前列标题重复,并将行数据跨出到水平组中。这里没有求和或聚合。这就是为什么PIVOT似乎不起作用,除非我错过了我希望的东西


SQL Server 2012

下面是一个使用动态交叉表的示例,正如SQL Server central的Jeff Moden的文章所建议的那样

他的文章可以在这里找到


我不确定pivot是否有帮助,因为我想您的类型数量未知。@xpy:对于数量未知的类型,可以对pivot使用动态sql……这在这里和整个internet上已经得到了数百次的回答。只需搜索动态轴心或动态交叉表。这里是我最喜欢的方法和关于这个主题的文章的链接@SeanRange PIVOT的问题,我没有看到答案,相信我,我已经搜索过了!我不仅仅希望行的值变成列。如果你看这个问题,我想让列名以分组的形式重复,并且相同的数据仍然在行中,只是分组。是的,我看到了。那你真的需要看看我贴的那篇文章。使用动态交叉表的一个好处是你有这种灵活性,这是动态轴心所没有的。我纠正了,这解决了问题!我有一些工作要做,以使它适合我的表,但我在一个简单的表上使用它,它正确地重复了列组。谢谢很高兴这对你有用。真正的诀窍是使用计数表作为聚合的基础。哦,请确保您理解该代码。这不是有史以来最简单的t-sql,当电话铃响时,你将是支持它的人谢谢你,我想我明白了,但我一定要自己再写一遍才能完全理解。
if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something
(
    ID char(1)
    , Phone int
    , MyType varchar(10)
)

insert #Something
select 'A', 111, 'home' union all
select 'A', 222, 'work' union all
select 'B', 333, 'cell' union all
select 'B', 444, 'school'

select *
from #Something

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

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


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
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS 
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)

select @DynamicPortion = @DynamicPortion + 
    ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Phone end) as Phone' + CAST(N as varchar(6)) +
    ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then MyType end) as Type' + CAST(N as varchar(6))

from cteTally t
where t.N <= 
(
    select top 1 Count(*)
    from #Something
    group by ID
    order by COUNT(*) desc
)

select @StaticPortion + @DynamicPortion + @FinalStaticPortion

declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;
exec sp_executesql @SqlToExecute