2009-12-08 3 views
0

값에 대한 개수가있는 테이블을 XML로 변환해야한다는 요구 사항이 있습니다.패싯 그룹화 및 개수로 TSQL을 사용하는 XML 테이블

Table 
Id , Type, AnotherType 
1, This, Widget 
2, This, Fimble 
3, That, Widget 

출력이 이와 같습니다. 이것은 동적이어야하므로 새 열이나 패싯을 추가하면이 유형의 출력이 생성됩니다.

<matrix name="Type"> 
<facet name = "this" count=2> 
    <id value = 1></id> 
    <id value = 2></id> 
</facet>  
<facet name = "that" count=1> 
    <id value = 3></id> 
</facet> 
</matrix> 
<matrix name="AnotherType"> 
<facet name = "Widget" count=2> 
    <id value = 1></id> 
    <id value = 3></id> 
</facet> 
<facet name = "Fimble" count=1> 
    <id value = 2></id> 
</facet> 
</matrix> 

이것은 가능합니까?

열/값이 변경되면이를 처리하는 솔루션이 필요합니다. 예를 들어 데이터에 따라 새로운 행렬 및 사실을 생성합니다.

답변

2

이 작업을 수행 할 수 있지만 UNPIVOT 명령과 동적 SQL을 적용해야합니다. 이 단계로 나누면 더 좋습니다 :

1) 테이블에 여러 열이있을 수 있습니다. 먼저 열의 목록을 가져와야합니다. 모든 열은 sys.columns 테이블에 나열되어 있습니다. 다음 코드는 열 목록을 가져 와서 쉼표로 구분 된 목록으로 저장합니다. 그러나 첫 번째 열은 다른 목적으로 분리되어 저장됩니다.

DECLARE @firstColumn NVARCHAR(256) 
DECLARE @columnList NVARCHAR(MAX) 

SELECT @firstColumn = name 
    FROM sys.columns 
    WHERE object_id = OBJECT_ID(@tableName) 
     AND column_id = 1 
SET @columnList = N'' 

SELECT @columnList = @columnList + name + N',' 
    FROM sys.columns 
    WHERE object_id = OBJECT_ID(@tableName) 
     AND column_id > 1 

SET @columnList = LEFT(@columnList,LEN(@columnList)-1) 

2) 당신은 구조 더 "프로그래머가 친숙한"할 UNPIVOT (documentation here) 명령을 사용합니다. 우리는 그것을하기 위해 기둥 목록이 필요합니다. 동적 SQL (example here)을 사용하여 수행 할 수 있습니다. 이 같은 결과를 생성합니다 귀하의 예에서

DECLARE @cmd NVARCHAR(MAX) 

SET @cmd = N'INSERT INTO #unPivoted 
    SELECT id, Matrixes, Facets 
    FROM 
     (SELECT ' + @firstColumn + N',' + @columnList + N' FROM ' + @tableName + N') p 
    UNPIVOT 
     (Facets FOR Matrixes IN(' + @columnList + N')) AS unpvt 
    ORDER BY Matrixes,Facets,id' 

EXEC sp_executesql @cmd 

: 다음 명령은 작업을 수행

id | Matrixes | Facets 
------------------------- 
2 | AnotherType | Fimble 
1 | AnotherType | Widget 
3 | AnotherType | Widget 
3 | Type  | That 
1 | Type  | This 
2 | Type  | This 

3) 마지막 것은 실제 쿼리입니다. FOR XML AUTO 명령을 사용하면됩니다. 그러나 구조를 원하는 모양으로 만들기 위해 중첩 된 쿼리를 만들어야합니다.

그리고 저장 프로 시저. 나는 당신이 모든 인쇄물과 선택을 남겨 두어 설명이 충분하지 않다면 어떻게 작동하는지 보았다.

CREATE PROCEDURE usp_tableToXML 
    @tableName NVARCHAR(256) 
AS 
BEGIN 

SET NOCOUNT ON; 

-- 1. Get columns from the table 
DECLARE @firstColumn NVARCHAR(256) 
DECLARE @columnList NVARCHAR(MAX) 

SELECT @firstColumn = name 
FROM sys.columns 
WHERE object_id = OBJECT_ID(@tableName) 
AND column_id = 1 

SET @columnList = N'' 

SELECT @columnList = @columnList + name + N',' 
FROM sys.columns 
WHERE object_id = OBJECT_ID(@tableName) 
AND column_id > 1 

SET @columnList = LEFT(@columnList,LEN(@columnList)-1) 

PRINT @firstColumn 
PRINT @columnList 

-- 2. Unpivot the table 
CREATE TABLE #unPivoted 
(
    id INT, 
    Matrixes VARCHAR(30), 
    Facets VARCHAR(30) 
) 

DECLARE @cmd NVARCHAR(MAX) 

SET @cmd = N'INSERT INTO #unPivoted 
SELECT id, Matrixes, Facets 
FROM 
    (SELECT ' + @firstColumn + N',' + @columnList + N' FROM ' + @tableName + N') p 
UNPIVOT 
    (Facets FOR Matrixes IN(' + @columnList + N')) AS unpvt 
ORDER BY Matrixes,Facets,id' 

PRINT @cmd 

EXEC sp_executesql @cmd 

SELECT * FROM #unPivoted 

-- 3. The query 
SELECT matrix.name, facet.name, facet.id_count AS count, id.id AS value 
FROM 
    (SELECT DISTINCT Matrixes AS name FROM #unPivoted) matrix 
INNER JOIN 
    (SELECT Matrixes AS matrix_name, Facets AS name, COUNT(id) AS id_count FROM #unPivoted GROUP BY Matrixes, Facets) facet 
    ON matrix.name = facet.matrix_name 
INNER JOIN 
    (SELECT Facets AS facet_name, id FROM #unPivoted) id 
    ON facet.name = id.facet_name 
ORDER BY matrix.name, facet.name, id.id 
FOR XML AUTO 

END 
GO 

EXEC usp_tableToXML 'Types' 

Btw, 나는 XML 구조를 약간 잘못했다고 생각합니다. 그것은 (? facet 태그 식별자 후 닫아야)이처럼 안 :

<matrix name="AnotherType"> 
    <facet name="Fimble" count="1"> 
    <id value="2" /> 
    </facet> 
    <facet name="Widget" count="2"> 
    <id value="1" /> 
    <id value="3" /> 
    </facet> 
</matrix> 
<matrix name="Type"> 
    <facet name="That" count="1"> 
    <id value="3" /> 
    </facet> 
    <facet name="This" count="2"> 
    <id value="1" /> 
    <id value="2" /> 
    </facet> 
</matrix> 
+0

놀라운, 매력처럼 작동하는 것 같습니다. – Coolcoder

+0

필자는 이것을 받아 들였지만 이상적으로는 테이블이 아닌 훌륭한 작업으로 쿼리를 처리해야합니다. 정말 좋은 물건. – Coolcoder

+0

나는이 코드를 사용하여 proc 내에서 코드가 사용되도록했다. 다시 환상적입니다. – Coolcoder

0

SQL Server 2005 이상을 사용하는 경우 this과 같은 작업을 수행 할 수 있습니다.

+0

이 출력 XML에, 나는이 내 질문에 대한 해결책이라고 생각하지 말아 방법에 불과 게시물입니다. – Coolcoder

0

여기를 보시기 바랍니다 : CTE and Hierarchical XML Result. XSLT 부분을 무시하고 XML 만 사용하면됩니다.

편집 : 조금 더 트릭입니다. 여기에서보십시오 : SQL XML output to populate a treeview 순수한 TSQL CTE 명령을 사용하여 계층 적 XML을 생성합니다.

+0

이것은 우아한 솔루션이나 내 시나리오에서 효과가있는 것처럼 보이지 않습니다. 나는 또한 순수한 TSQL 솔루션을 원한다. 아마도 CTE를 명시 적 XML과 함께 사용하는 것이 가능할 것이라고 확신한다. – Coolcoder