如何将行值分组为列?

时间:2013-07-20 10:40:09

标签: sql sql-server-2008 tsql

如下表所示

Animal        LiveIn
------        ------

Cat           land
fish          water
frog          land
frog          water
salamander    land
salamander    water

我需要如下结果

Animal        Column1    Column2
------        -------    -------
cat           land       *null*
fish          water      *null*
frog          land       water
salamander    land       water

3 个答案:

答案 0 :(得分:2)

我建议您使用row_number()和条件聚合:

执行此操作
select t.animal,
       max(case when seqnum = 1 then livein end) as Column1,
       max(case when seqnum = 2 then livein end) as Column2
from (select t.*, row_number() over (partition by animal order by (select NULL)) as seqnum
      from t
     ) t
group by t.animal;

请注意,您无法表达数据中列的顺序 - SQL表本质上是无序的。以上选择任意顺序。如果您有idCreatedAt列,则可以使用该列指定订单。

鉴于没有订购,以下也做了同等的工作:

select t.animal, min(t.LiveIn) as Column1,
       (case when min(t.LiveIn) <> max(t.LiveIn) then max(t.LiveIn) end) as Column2
from t
group by t.animal;

编辑:

SQL查询必须返回固定数量的列。您无法查询有时返回三列,有时返回四列。但是,您可以调整查询以返回更多列,通常可能是NULL

select t.animal, count(*) as NumLiveIn,
       max(case when seqnum = 1 then livein end) as Column1,
       max(case when seqnum = 2 then livein end) as Column2,
       max(case when seqnum = 3 then livein end) as Column3,
       max(case when seqnum = 4 then livein end) as Column4
from (select t.*, row_number() over (partition by animal order by (select NULL)) as seqnum
      from t
     ) t
group by t.animal;

在这种情况下,我还会为环境数添加一列。

答案 1 :(得分:1)

你的代码令人困惑;什么是'-----'应该向我展示?

您有重复的值以及想要“分组”它们的权利。 看看规范化,因为您似乎参与了数据库的模式级别并要求DDL codehttps://en.wikipedia.org/wiki/Database_normalization

如果前两个'------'实际上是两个表,我建议对该模式进行以下修改。

Animal    Environment    Animal_Environment
------    ------         ------
id        id             animal_id
name      name           environment_id

有了这个,我们避免重复数据库中的内容。 对于该内容,也会导致更简单的DML queries

答案 2 :(得分:1)

这不是你要求的,但它是另一种解决方法:

declare @t table(Animal varchar(10), LiveIn varchar(7))
insert @t values
('Cat','land'),('fish','water'),('frog','land'),
('frog','water'),('salamander','land'),('salamander','water')

select * from @t
PIVOT
(min([LiveIn])  
FOR Livein
in([land],[water])  
)AS p ORDER BY 1

结果:

Animal     land  Water
______________________
Cat        land  NULL
fish       NULL  water
frog       land  water
salamander land  water