在SQL中将行转换为列

时间:2010-05-13 20:38:23

标签: sql-server pivot

我有一张桌子(实际上是一个视图,但我的示例简化为一个表格),它给了我一些像这样的数据

 CompanyName website
 Google         google.com
 Google         google.net
 Google         google.org
 Google         google.in
 Google         google.de
 Microsoft       Microsoft.com
 Microsoft       live.com
 Microsoft       bing.com
 Microsoft       hotmail.com

我希望转换它以获得像这样的结果

CompanyName website1      website2   website3   website 4   website5  website6 
----------- ------------- ---------- ---------- ----------- --------- --------
Google      google.com    google.net google.org google.in   google.de NULL
Microsoft   Microsoft.com live.com   bing.com   hotmail.com NULL      NULL

我已经研究过pivot,但看起来记录(行值)不能是动态的(即只能是某些预定义的值)。

此外,如果有超过6个网站,我想将其限制在前6个

动态支点是有意义的,但我必须将它合并到我的视图中?对此有更简单的解决方案吗?

以下是SQL脚本

CREATE TABLE [dbo].[Company](

 [CompanyName] [varchar](50) NULL,
 [website] [varchar](50) NULL
) ON [PRIMARY]
GO

insert into company values ('Google','google.com')
insert into company values ('Google','google.net')
insert into company values ('Google','google.org')
insert into company values ('Google','google.in')
insert into company values ('Google','google.de')
insert into company values ('Microsoft','Microsoft.com')
insert into company values ('Microsoft','live.com')
insert into company values ('Microsoft','bing.com')
insert into company values ('Microsoft','hotmail.com')

编辑:我删除了为简化而创建的ID。我想我不应该拥有它。关于它。

3 个答案:

答案 0 :(得分:2)

如果您使用的是SQL Server 2005+,则可以执行以下操作:

With NumberedSites As
    (
    Select CompanyName, Website
        , ROW_NUMBER() OVER( PARTITION BY CompanyName ORDER BY Id ) As Num
    From Table
    )
Select CompanyName
    , Min( Case When Num = 1 Then Website End ) As Website1
    , Min( Case When Num = 2 Then Website End ) As Website2
    , Min( Case When Num = 3 Then Website End ) As Website3
    , Min( Case When Num = 4 Then Website End ) As Website4
    , Min( Case When Num = 5 Then Website End ) As Website5
    , Min( Case When Num = 6 Then Website End ) As Website6
From NumberedSites
Where Num <= 6
Group By CompanyName

现在,这个解决方案显然不是动态的,并假设有六列(七个包括公司名称)。如果你想要一组动态的列,唯一的方法是使用一些非常动态的SQL代码。相反,如果你想要一个动态交叉表,我建议你在中间层或报告工具中这样做。

答案 1 :(得分:2)

试试这个:

DECLARE @Company table (
    [id] [int] NULL,
    [CompanyName] [varchar](15) NULL,
    [website] [varchar](15) NULL
) 

insert into @company values (1,'Google','google.com')
insert into @company values (2,'Google','google.net')
insert into @company values (3,'Google','google.org')
insert into @company values (4,'Google','google.in')
insert into @company values (5,'Google','google.de')
insert into @company values (6,'Microsoft','Microsoft.com')
insert into @company values (7,'Microsoft','live.com')
insert into @company values (8,'Microsoft','bing.com')
insert into @company values (9,'Microsoft','hotmail.com')

;WITH CompanyGrouped AS
(   SELECT
        *,ROW_NUMBER() OVER(PARTITION BY CompanyName ORDER BY CompanyName, id) AS ColumnNumber
        FROM @company
)
SELECT DISTINCT
    t.CompanyName
        ,t1.website AS website1,t2.website AS website2,t3.website AS website3, t4.website AS website4, t5.website AS website5, t6.website AS website6
    FROM @Company                      t
        LEFT OUTER JOIN CompanyGrouped t1 ON t.CompanyName=t1.CompanyName AND t1.ColumnNumber=1
        LEFT OUTER JOIN CompanyGrouped t2 ON t.CompanyName=t2.CompanyName AND t2.ColumnNumber=2
        LEFT OUTER JOIN CompanyGrouped t3 ON t.CompanyName=t3.CompanyName AND t3.ColumnNumber=3
        LEFT OUTER JOIN CompanyGrouped t4 ON t.CompanyName=t4.CompanyName AND t4.ColumnNumber=4
        LEFT OUTER JOIN CompanyGrouped t5 ON t.CompanyName=t5.CompanyName AND t5.ColumnNumber=5
        LEFT OUTER JOIN CompanyGrouped t6 ON t.CompanyName=t6.CompanyName AND t6.ColumnNumber=6

输出:

CompanyName website1      website2   website3   website4    website5  website6
----------- ------------- ---------- ---------- ----------- --------- --------
Google      google.com    google.net google.org google.in   google.de NULL
Microsoft   Microsoft.com live.com   bing.com   hotmail.com NULL      NULL

(2 row(s) affected)

答案 2 :(得分:0)

我必须为我的工作处理类似的报告,但我从不同的方向来看它。我编写了(aped)一个SQL CLR自定义聚合,将网站列表汇总为逗号分隔的字符串。

例如:

--load the temp table named Company from your example
--then run this query
SELECT CompanyName, StringUtil.Concat(Website) AS WebSites FROM Company

--outputs:

CompanyName Websites
----------- ---------------------------------------------------
Google      google.com, google.net, google.org, google.in, google.de
Microsoft   microsoft.com, live.com, bing.com, hotmail.com

(2 row(s) affected)

构建/安装/使用CLR自定义聚合的代码和说明随SQL Server(2005及更高版本)一起提供,但通常不会安装。 这些文档位于MSDN http://msdn.microsoft.com/en-US/library/ms161551(v=SQL.90).aspx