2017-05-22 1 views
0

정렬 할 열의 값을 바꾸고 싶습니다.SQL Server : 행의 열 순서

테이블 :

pid | category1 | category2 | category3 
----+-----------+-----------+---------- 
1 | a  | b  | 
2 | b  | a  | 
3 | a  | c  | b 

결과는 다음과 같아야합니다

pid | category 
----+--------- 
1 | a 
1 | b 
2 | b 
2 | a 
3 | a 
3 | c 
3 | b 
:

pid | category1 | category2 | category3 
----+-----------+-----------+---------- 
1 | a  | b  | 
2 | a  | b  | 
3 | a  | b  | c 

내 접근 방식은 새로운 열의 반환에게 그룹을 주문, 행과 열을 선택하는 것이 었습니다

피벗 기능을 찾았지만이 컨텍스트에서이를 사용하는 방법을 실제로 이해하지 못했습니다.

+0

당신이'4 같은 행과 어떻게 할 것인지 | b | c | '? – SqlZim

+2

가장 좋은 방법은이 데이터를 영구히 정규화하는 것입니다. 그러면 그것은 사소한 것이됩니다. category1, category2와 같은 열이있는 경우 그룹을 반복하여 1NF를 위반합니다. –

+0

나는 피벗하지 않는 피벗을 원한다고 생각합니다. @SeanLange가 제안한대로 더 정상화 될 것입니다. – scsimon

답변

1

Sean Lange는 데이터베이스 스키마를 수정하는 방법에 대해 옳습니다. 여기

그때까지 당신에게 당신의 결과를 얻을 수있는 무언가이다 : row_number()와 함께 데이터를 피벗 해제 할 cross apply(values ...)를 사용

이 순서 당신의 categorycommon table expression를 내부; 다음 조건 집합으로 데이터를 repivoting :

;with cte as (
select 
    t.pid 
    , u.category 
    , rn = row_number() over (partition by t.pid order by u.category) 
from t 
    cross apply (values (category1),(category2),(category3)) u(category) 
where nullif(u.category,'') is not null 
) 
select 
    pid 
    , category1 = max(case when rn = 1 then category end) 
    , category2 = max(case when rn = 2 then category end) 
    , category3 = max(case when rn = 3 then category end) 
from cte 
group by pid 

rextester 데모 : http://rextester.com/GIG22558

반환 :

+-----+-----------+-----------+-----------+ 
| pid | category1 | category2 | category3 | 
+-----+-----------+-----------+-----------+ 
| 1 | a   | b   | NULL  | 
| 2 | a   | b   | NULL  | 
| 3 | a   | b   | c   | 
+-----+-----------+-----------+-----------+ 
0

당신이 피벗 수만큼 아래에 출력

select * from (
    select *, RowN = row_number() over(partition by pid order by Category) from Categories 
    ) a 
    pivot (max(category) for RowN in ([1],[2],[3])) p 

아래 :

당신은 다음과 같이 사용할 수있는 열 동적 목록 (210)
+-----+-----------+-----------+-----------+ 
| Pid | Category1 | Category2 | Category3 | 
+-----+-----------+-----------+-----------+ 
| 1 | a   | b   | NULL  | 
| 2 | a   | b   | NULL  | 
| 3 | a   | b   | c   | 
+-----+-----------+-----------+-----------+ 

:

declare @cols1 varchar(max) 
declare @cols2 varchar(max) 
declare @query nvarchar(max) 

--Row Numbers with tally 
;with c1 as (
select * from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) v(n)) 
,c2 as (select n1.* from c1 n1, c1 n2, c1 n3, c1 n4) 
,RowNumbers as ( 
select top (select max(cnt) from (select cnt = count(*) from Categories group by pid) a) convert(varchar(6), row_number() over (order by (select null))) as RowN 
from c2 n1, c2 n2 
) 
select @cols1 = stuff((select ','+QuoteName(RowN) from RowNumbers group by RowN for xml path('')),1,1,''), 
     @cols2 = stuff((select ',' + QuoteName(RowN) + ' as '+ QuoteName(concat('Category' , RowN)) from RowNumbers group by RowN for xml path('')),1,1,'') 

select @cols1, @cols2 

Set @query = ' Select Pid, '+ @cols2 +' from (' 
Set @query += '  select *, RowN = row_number() over(partition by pid order by Category) from Categories) a ' 
Set @query += ' pivot (max(category) for RowN in (' + @cols1 + ')) p' 

--select @query 
exec sp_executesql @query 
+0

고마워요. 훌륭한 직업, 이것은 아주 좋은 해결책 인 것 같습니다. –

+0

환영합니다 ... 행복한 코딩 –