我需要将表格转换为具有值计数的XML。
e.g。
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>
这可能吗?
如果列/值发生变化,我想要一个处理它的解决方案 - 例如,它会生成一个新的矩阵和依赖于数据的事实。
答案 0 :(得分: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
命令就足够了。但是,您应该进行一些嵌套查询以使结构看起来像您想要的那样:
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
和存储过程。我留下了所有的PRINT和SELECT,看看它是如何工作的(如果没有描述的话)。
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'
不过,我猜你在XML结构中犯了一点错误。不应该是这样的(facet
标签应该在ID之后关闭吗?):
<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>
答案 1 :(得分:0)
如果您有SQL Server 2005或更高版本,则可以执行this之类的操作。
答案 2 :(得分:0)
请看一下:CTE and Hierarchical XML Result。您可以忽略XSLT部分并坚持使用XML。
编辑:似乎有点诡计。请看这里:SQL XML output to populate a treeview因为它使用纯TSQL CTE指令来生成分层XML。