2012-02-22 2 views
2

PersonID에 대한 주소를 얻기위한 쿼리를 작성하고 있습니다. 다음 쿼리는 나를 위해 작동하지만 두 개의 주소로만 반환됩니다. 단일 쿼리로 'n'개의 주소를 처리하고 싶습니다. 이 일을 할 수있는 방법이 있습니까?PIVOT을 사용하여 Select 쿼리에서 열을 동적으로 선언하는 방법

많은 감사 다음 표와 샘플 데이터를 가정

SELECT 
    PersonID, PersonName 
    [Address1], [Address2] 
FROM 
    (
    SELECT 
    P.PersonID, 
    P.PersonName, 
    (ROW_NUMBER() OVER(PARTITION BY P.PersonID ORDER BY A.AddressID)) RowID 
    FROM tblPerson 
    INNER JOIN tblAddress AS A ON A.PersonID = P.PersonID 
) AS AddressTable 
PIVOT 
    (
    MAX(AddressID) 
    FOR RowID IN ([Address1], [Address2]) 
) AS PivotTable; 
+1

Itzik Ben-Gan (SQL Server MVP)에는 동적 피벗의 표준 예가 있습니다. 인터넷 검색을 사용하면 많은 리소스를 찾을 수 있습니다. 또한, 여기 : http://stackoverflow.com/q/2922797/112196. 그럼에도 불구하고 이것을 달성하기 위해 동적 SQL을 생성하고 실행해야합니다. –

+0

http://stackoverflow.com/questions/2209700/how-to-use-pivot-in-sql-server-2005-stored-procedure-joining-two-views 가능한 중복 –

+0

동적 SQL로 이동해야합니다. 컴파일 할 때 모든 쿼리는 특정 모양 (즉, 특정 유형의 각 행이 준수 할 이름이 지정된 열 집합)을 사용하여 결과 집합을 반환해야합니다. –

답변

6

:

USE tempdb; 
GO 

CREATE TABLE dbo.tblPerson(PersonID INT, PersonName VARCHAR(255)); 

INSERT dbo.tblPerson SELECT 1, 'Bob' 
      UNION ALL SELECT 2, 'Charlie' 
      UNION ALL SELECT 3, 'Frank' 
      UNION ALL SELECT 4, 'Amore'; 

CREATE TABLE dbo.tblAddress(AddressID INT, PersonID INT, [Address] VARCHAR(255)); 

INSERT dbo.tblAddress SELECT 1,1,'255 1st Street' 
      UNION ALL SELECT 2,2,'99 Elm Street' 
      UNION ALL SELECT 3,2,'67 Poplar Street' 
      UNION ALL SELECT 4,2,'222 Oak Ave.' 
      UNION ALL SELECT 5,1,'36 Main Street, Suite 22' 
      UNION ALL SELECT 6,4,'77 Sicamore Ct.'; 

다음 쿼리는 원하는 결과를 얻을, 그것은 0, 1 또는 n 주소를 처리하는 방법을 보여줍니다. 이 경우 가장 높은 숫자는 3이지만 샘플 데이터를 약간 조정하여 원하는 경우 더 많은 주소로 재생할 수 있습니다. 당신이 그것을 실행하면

;WITH xMaster AS 
(
    SELECT PersonID, Address, 
    rn = ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY Address) 
    FROM dbo.tblAddress 
) 
SELECT PersonID, PersonName,[Address1],[Address2],[Address3] FROM 
    (
     SELECT p.PersonID, p.PersonName, 
[Address1] = x1.Address, 
[Address2] = x2.Address, 
[Address3] = x3.Address 
FROM dbo.tblPerson AS p 
LEFT OUTER JOIN xMaster AS x1 ON x1.PersonID = p.PersonID AND x1.rn = 1 
LEFT OUTER JOIN xMaster AS x2 ON x2.PersonID = p.PersonID AND x2.rn = 2 
LEFT OUTER JOIN xMaster AS x3 ON x3.PersonID = p.PersonID AND x3.rn = 3 
) AS Addresses; 

,이 표시됩니다 :

enter image description here

내가 얻을 수있는 쿼리를 알고 당신은 SQL을 인쇄 할 경우

DECLARE @col NVARCHAR(MAX) = N'', 
     @sel NVARCHAR(MAX) = N'', 
     @from NVARCHAR(MAX) = N'', 
     @query NVARCHAR(MAX) = N''; 

;WITH m(c) AS 
(
    SELECT TOP 1 c = COUNT(*) 
    FROM dbo.tblAddress 
    GROUP BY PersonID 
    ORDER BY c DESC 
) 
SELECT @col = @col + ',[Address' + RTRIM(n.n) + ']', 
    @sel = @sel + ',' + CHAR(13) + CHAR(10) + '[Address' + RTRIM(n.n) + '] = x' 
     + RTRIM(n.n) + '.Address', 
    @from = @from + CHAR(13) + CHAR(10) + ' LEFT OUTER JOIN xMaster AS x' 
     + RTRIM(n.n) + ' ON x' + RTRIM(n.n) + '.PersonID = p.PersonID AND x' 
     + RTRIM(n.n) + '.rn = ' + RTRIM(n.n) 
FROM m CROSS JOIN (SELECT n = ROW_NUMBER() OVER (ORDER BY [object_id]) 
    FROM sys.all_columns) AS n WHERE n.n <= m.c; 

SET @query = N';WITH xMaster AS 
(
    SELECT PersonID, Address, 
    rn = ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY Address) 
    FROM dbo.tblAddress 
) 
SELECT PersonID, PersonName' + @col 
+ ' FROM 
    (
     SELECT p.PersonID, p.PersonName, ' + STUFF(@sel, 1, 1, '') 
+ CHAR(13) + CHAR(10) + ' FROM dbo.tblPerson AS p ' + @from + ' 
) AS Addresses;'; 

PRINT @query; 
--EXEC sp_executesql @query; 

이 결과를 볼 수 있습니다 여기는 못생긴 엉망이지만, 당신의 요구 사항에 따라 달라집니다. 내 의견에서 제안한대로 쉼표로 구분 된 목록을 반환하거나 피벗 계층을 프레젠테이션 계층에서 다루는 것이 더 쉬울 것입니다.

+1

+1 스팟 켜기 .... 많은 감사합니다 @ 애런 버트 랜드 – Scorpion

관련 문제