집계 함수가없는 TSQL 피벗


139

나는 이런 식으로 테이블을 가지고있다 ...

CustomerID   DBColumnName   Data
--------------------------------------
1            FirstName      Joe
1            MiddleName     S
1            LastName       Smith
1            Date           12/12/2009
2            FirstName      Sam
2            MiddleName     S
2            LastName       Freddrick
2            Date           1/12/2009
3            FirstName      Jaime
3            MiddleName     S
3            LastName       Carol
3            Date           12/1/2009

그리고 나는 이것을 원한다 ...

PIVOT을 사용하여 가능합니까?

CustomerID  FirstName   MiddleName          LastName        Date
----------------------------------------------------------------------
1           Joe             S               Smith           12/12/2009
2           Sam             S               Freddrick       1/12/2009
3           Jaime           S               Carol           12/1/2009

답변:


102

MAX 집계를 사용할 수 있지만 여전히 작동합니다. 하나의 값의 MAX = 해당 값 ..

이 경우 customerid에서 5 번 자체 조인하고 테이블 참조 당 dbColumnName으로 필터링 할 수도 있습니다. 더 잘 작동 할 수 있습니다.


1
같은 이름을 가진 2 명의 코스튬 플레이어가 있다면 실제로 작동하지 않습니다
Leonardo

1
작동합니다. DBColumnName은 메타 데이터임을 기억하십시오. 문자 그대로 "CustomerID = 1 AND DBColumnName = 'FirstName'"으로 필터링합니다. 물론, 주어진 CustomerID에 대해 여러 개의 FirstName 행이 있지만 테이블을 올바르게 작성하는 경우 CustomerID와 DBColumnName이 모두 기본 키의 일부입니다.
4AM

7
예를 들어 일부 코드 / 조롱은 훌륭 했으며이 답변을 완벽하게 완성했습니다.
DavidScherer

167

예, 그러나 왜 !! ??

   Select CustomerID,
     Min(Case DBColumnName When 'FirstName' Then Data End) FirstName,
     Min(Case DBColumnName When 'MiddleName' Then Data End) MiddleName,
     Min(Case DBColumnName When 'LastName' Then Data End) LastName,
     Min(Case DBColumnName When 'Date' Then Data End) Date
   From table
   Group By CustomerId

2
^^ 이것은 나를 위해 일했다. PIVOT은 숫자가 아닌 값에 효율적이지 않습니다.
Dienekes

6
이것은 훌륭한 대안입니다. Pivot쿼리에서 사용 하고 나서 이것을 전환하고 실행 계획을 살펴 보았습니다. 이 방법은 8 %, 피벗 방식은 92 %가 소요되었습니다!
mafue

2
@CharlesBretana, 당신은 훌륭합니다! 당신은 내 영혼을 구했습니다! ) 이것이 최선의 해결책입니다. 감사!
Chaki_Black

3
이 솔루션을 정말로 좋아합니다. 또한 열에 피벗 대신 올바른 데이터가 포함되어 있는지 확인하십시오. 감사합니다!
Tenerezza

2
이것은 훌륭합니다! 하지만 어떻게 방지 할 수 Warning: Null value is eliminated by an aggregate or other SET operation
있습니까

24
WITH pivot_data AS
(
SELECT customerid, -- Grouping Column
dbcolumnname, -- Spreading Column
data -- Aggregate Column
FROM pivot2 
)
SELECT customerid, [firstname], [middlename], [lastname]
FROM pivot_data
PIVOT (max(data) FOR dbcolumnname IN ([firstname],[middlename],[lastname])) AS p;

3
TSQL Pivot 명령의 올바른 사용법을 보여주기 때문에 허용되는 답변이어야합니다.
Ubercoder

1
이 쿼리에서 "pivot2"는 원본 데이터가있는 테이블의 이름입니다. 또한 여기에서 CTE를 사용하는 것은 불필요 SELECT합니다. CTE 아래의 명령문은 원래 테이블의 이름을 지정했을 수 있습니다.
STLDev

@STLDev 실제로 STLDev는 피벗이 작동하는 방식이 아닙니다. 테이블 "pivot2"의 모든 열을 알 수 없습니다. 실제로 OP가 테이블에 지정하지 않은 다른 열이있을 수 있습니다. 따라서 CTE 또는 파생 테이블 쿼리를 사용하여 열을 제한하지 않으면 테이블의 모든 열이 그룹화에 사용됩니다. 다시 말해, PIVOT은 우리가 기대하는 것은 아니지만 무언가를 반환합니다. 이것은 70-761 인증 시험에 대한 심층적 인 개념입니다.
Zorkolot

2
PIVOT은 PIVOT 자체에서 사용되지 않은 열을 기준으로 자동 그룹화한다는 점에 주목할 가치가 있습니다. 따라서이 예에서 [data] 및 [dbcolumnname]은 PIVOT에 있으므로 모든 것이 [CustomerId]
Sal

9
SELECT
main.CustomerID,
f.Data AS FirstName,
m.Data AS MiddleName,
l.Data AS LastName,
d.Data AS Date
FROM table main
INNER JOIN table f on f.CustomerID = main.CustomerID
INNER JOIN table m on m.CustomerID = main.CustomerID
INNER JOIN table l on l.CustomerID = main.CustomerID
INNER JOIN table d on d.CustomerID = main.CustomerID
WHERE f.DBColumnName = 'FirstName' 
AND m.DBColumnName = 'MiddleName' 
AND l.DBColumnName = 'LastName' 
AND d.DBColumnName = 'Date' 

편집 : 나는 편집기없이 이것을 작성했으며 SQL을 실행하지 않았습니다. 나는 당신이 아이디어를 얻길 바랍니다.


9

좋아요, 불쌍한 질문에 대해 죄송합니다. gbn은 나를 올바른 길로 안내했다. 이것이 내가 대답에서 찾은 것입니다.

SELECT [FirstName], [MiddleName], [LastName], [Date] 
FROM #temp 
PIVOT
(   MIN([Data]) 
    FOR [DBColumnName] IN ([FirstName], [MiddleName], [LastName], [Date]) 
)AS p

그런 다음 while 문을 사용하고 위의 문을 varchar로 작성하고 dynmaic sql을 사용해야했습니다.

이와 같은 것을 사용하여

SET @fullsql = @fullsql + 'SELECT ' + REPLACE(REPLACE(@fulltext,'(',''),')','')
SET @fullsql = @fullsql + 'FROM #temp '
SET @fullsql = @fullsql + 'PIVOT'
SET @fullsql = @fullsql + '('
SET @fullsql = @fullsql + ' MIN([Data])'
SET @fullsql = @fullsql + ' FOR [DBColumnName] IN '+@fulltext
SET @fullsql = @fullsql + ')'
SET @fullsql = @fullsql + 'AS p'

EXEC (@fullsql)

while 루프를 사용하여 @fulltext를 작성하고 테이블에서 고유 한 열 이름을 선택하십시오. 답변 주셔서 감사합니다.


6

OP는 실제로 집계없이 피벗 할 필요는 없지만 여기에 오는 사람들은 어떻게 볼 수 있는지 알 수 있습니다.

SQL 매개 변수화 된 CTE 쿼리

이 질문에 대한 답은 집계없는 피벗이 필요한 상황을 포함하므로이를 수행하는 예가 솔루션의 일부입니다.


1

이 시도:

SELECT CUSTOMER_ID, MAX(FIRSTNAME) AS FIRSTNAME, MAX(LASTNAME) AS LASTNAME ...

FROM
(

SELECT CUSTOMER_ID, 
       CASE WHEN DBCOLUMNNAME='FirstName' then DATA ELSE NULL END AS FIRSTNAME,
       CASE WHEN DBCOLUMNNAME='LastName' then DATA ELSE NULL END AS LASTNAME,
        ... and so on ...
GROUP BY CUSTOMER_ID

) TEMP

GROUP BY CUSTOMER_ID

1

이것은 작동해야합니다 :

select * from (select [CustomerID]  ,[Demographic] ,[Data]
from [dbo].[pivot]
) as Ter

pivot (max(Data) for  Demographic in (FirstName, MiddleName, LastName, [Date]))as bro

1

피벗 쿼리에 대한 동적 필드를 작성하는 좋은 방법은 다음과 같습니다.

--tmp 테이블에 값을 요약

declare @STR varchar(1000)
SELECT  @STr =  COALESCE(@STr +', ', '') 
+ QUOTENAME(DateRange) 
from (select distinct DateRange, ID from ##pivot)d order by ID

--- 생성 된 필드를보십시오

print @STr

exec('  .... pivot code ...
pivot (avg(SalesAmt) for DateRange IN (' + @Str +')) AS P
order by Decile')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.