我有一个存储过程,它连接了许多表以生成一个大的结果集,然后返回给我的应用程序。应用程序依次遍历结果并组合特定ID上的行,并选择每行数据以包含在新对象中。使用示例解释这可能是最容易解释的:
Inspection, Desc, Value
1, Description1, 3
1, Description2, 2
1, Description3, 5
这是代码转为
Inspection, Description1, Description2, Description3
1, 3, 2, 5
这一点是每个检验项目有一行,项目描述为标题,值为检验行和标题的单元格值。然后将其导出到Excel。
问题是:我如何在SQL Server中执行此操作,如在扩展我的SP以返回更少但是更宽的"有更多列的行?
另一个复杂因素是,一个检查可能有另一个缺少的行,在这种情况下,解决方案是添加空值或“'”。
P.S。这是使用Sql Server 2012。
答案 0 :(得分:2)
如果您使用的是mssql 2005+。您可以使用这样的支点:
测试数据
DECLARE @tbl TABLE(Inspection INT, [Desc] VARCHAR(100),Value INT)
INSERT INTO @tbl
VALUES
(1,'Description1', 3),
(1,'Description2', 2),
(1,'Description3', 5)
<强>查询强>
SELECT
*
FROM
(
SELECT
tbl.Inspection,
tbl.[Desc],
tbl.Value
FROM
@tbl AS tbl
) AS tbl
PIVOT
(
SUM(Value)
FOR [Desc] IN ([Description1],[Description2],[Description3])
)AS pvt
<强>结果:强>
Inspection, Description1, Description2, Description3
1 3 2 5
修改强>
正如juharr在评论中所说:
生成的列名称(表中的值)是构建查询时的结果。这可能需要另一个初始查询来获取
修改2
如果您不使用mssql 2005+。或者想要和交替解释。请参阅以下查询:
SELECT
tbl.Inspection,
SUM(CASE WHEN [Desc]='Description1' THEN tbl.Value ELSE 0 END) AS Description1,
SUM(CASE WHEN [Desc]='Description2' THEN tbl.Value ELSE 0 END) AS Description2,
SUM(CASE WHEN [Desc]='Description3' THEN tbl.Value ELSE 0 END) AS Description3
FROM
@tbl AS tbl
GROUP BY
tbl.Inspection
这不需要一个支点,可以在大多数RDMS上使用
答案 1 :(得分:1)
您应该使用Sql Server Pivot
。它将行转换为列。您可以通过this example轻松开始。
答案 2 :(得分:0)
如果您想动态执行此操作,而无需知道所有Desc
值是什么,则可以构建您的数据透视查询并使用Exec()
或Execute sp_executesql
DECLARE @Columns NVARCHAR(MAX),
@Sql NVARCHAR(MAX)
--Build your column headers based on Distinct Desc values
SELECT @Columns = COALESCE(@Columns + ',', '') + QUOTENAME([Desc])
FROM (SELECT DISTINCT [Desc] FROM tbl) t
ORDER BY [Desc]
--Build your pivot query
SET @Sql = '
SELECT
*
FROM
tbl
PIVOT
(
MAX([Value])
FOR [Desc] IN (' + @Columns + ')
) p
'
EXEC(@Sql)
如果您希望-
为空值,则需要创建另一个变量来保存sql的Select
部分的转换脚本。
DECLARE @Columns NVARCHAR(MAX),
@Sql NVARCHAR(MAX),
@ColumnAliases NVARCHAR(MAX)
--Build your pivot columns based on Distinct Desc values
SELECT @Columns = COALESCE(@Columns + ',', '') + QUOTENAME([Desc])
FROM (SELECT DISTINCT [Desc] FROM tbl) t
ORDER BY [Desc]
--Build your column headers, replacing NULL with -
SELECT @ColumnAliases = COALESCE(@ColumnAliases + ',', '')
+ 'COALESCE(CONVERT(VARCHAR,' + QUOTENAME([Desc]) + '),''-'') AS ' + QUOTENAME([Desc])
FROM (SELECT DISTINCT [Desc] FROM tbl) t
ORDER BY [Desc]
--Build your pivot query
SET @Sql = '
SELECT
Inspection,'
+ @ColumnAliases + '
FROM
tbl
PIVOT
(
MAX([Value])
FOR [Desc] IN (' + @Columns + ')
) p
'
EXEC(@Sql)