SQL SERVER Pivot rows to column

时间:2018-12-19 11:24:47

标签: sql-server

I have the input as

123   1    Y    Active

123   1    Y    Idle

109   1    Y    Active

109   1    Y    Away

165   1    Y    Active

145   1    Y    Idle

I need the output as :

123  1  Y   Active and Idle

109  1  Y   Active and Away

165  1  Y   Active Only

145  1  Y   Idle Only

SELECT distinct COl1,Col2,Col3 ,
case when Col4 = 'Active' and Col4 = 'Idle' then 'Active and Idle'
when Col4 = 'Active' and Col4 = 'Away' then 'Active and Away'
when Col4 = 'Active' then  'Active Only'
when Col4 = 'Idle' then  'Idle Only'

end  as category
from Person

I tried the above query but it is not working and it wont work because i am trying to convert multiple rows to 1 column, which is not possible with Case.

I have to try something like PIVOT, but not able to implement . Any help?

3 个答案:

答案 0 :(得分:2)

You need FOR XML PATH() approach :

SELECT DISTINCT p.col1, STUFF(pp.Col4, 1, 4, '') AS category
FRPM Person p CROSS APPLY
     ( SELECT ' AND ' + p1.Col4 
       FROM Person p1
       WHERE P1.col1 = p.col1 
       FOR XML PATH('')
     ) pp(Col4);

By this way FOR XML PATH('') would return xml element for each col1 & outer query STUFF() will replace AND with '' at the start of position of string.

答案 1 :(得分:2)

尝试以下操作:

declare @table table(
col1 int,col2 int,col3 nvarchar(10),col4 nvarchar(50)
)

insert into @table values(123,   1,    'Y'    ,'Active')
insert into @table values(123,   1,    'Y'    ,'Idle')
insert into @table values(109,   1,    'Y'    ,'Active')
insert into @table values(109,   1,    'Y'    ,'Away')
insert into @table values(165,   1,    'Y'    ,'Active')
insert into @table values(145,   1,    'Y'    ,'Idle')


select col1,col2,col3, stuff((SELECT ' AND ' + t2.col4 + CASE WHEN count(t1.col1) = 1 THEN ' ONLY' ELSE '' END
                        FROM @table t2
                        WHERE t2.col1 = t1.col1
                        ORDER BY t2.col1
                        FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
            ,1,5,'') AS col4
from @table t1
group by col1,col2,col3

我正在使用stuff来合并该组中不包含的值。

count = 1表示该组中只有一项,因此您需要添加Only后缀。

答案 2 :(得分:1)

即使在提供STRING_AGG的SQL Server 2017中,这也不是一个显而易见的问题。如果每个组只有一行,则需要检查以附加Only

给出此表:

declare @table table (id int, flag1 int, flag2 char(1), status varchar(40))

insert into @table 
values
(123,1,'Y','Active'),
(123,1,'Y','Idle'),
(109,1,'Y','Active'),
(109,1,'Y','Away'),
(165,1,'Y','Active'),
(145,1,'Y','Idle')

以下查询将返回汇总值。如果只有一个值,它将附加Only

select id,flag1,flag2,
    string_agg(status,' and ') + IIF(count(*)>1,'',' Only')     
from @table
group by id,flag1,flag2

这产生了:

109 1   Y   Active and Away
123 1   Y   Active and Idle
145 1   Y   Idle Only
165 1   Y   Active Only