动态返回行中所有列的SUM

时间:2014-08-28 17:53:04

标签: sql sql-server tsql for-loop

有没有办法使用T-SQL动态地对连续返回的每列的值进行求和?我正在使用SQL Server 2008.我会想象有一些表值函数魔法可以实现这一点,但我在寻找答案时并不幸运。

数据如下:

id        type        value      date
1         PROD1       5          2014-08
2         PROD2       3          2014-08
3         PROD3       4          2014-08
4         PROD4       3          2014-08
5         PROD2       3          2014-07
6         PROD3       5          2014-06

TVF接受日期作为参数并返回:

PROD1 PROD2   PROD3   PROD4
5     3       4       3

现在我当然可以在原始表上运行以下命令:

SELECT * FROM tbl WHERE date = '2014-08'

然后回来

id        type        value      date
1         PROD1       5          2014-08
2         PROD2       3          2014-08
3         PROD3       4          2014-08
4         PROD4       3          2014-08

但是......我需要对这些值进行一些数学运算。我可能需要结合PROD1和PROD3的总和,或者可以得到SUM(PROD1,PROD3)占总SUM的百分比。

我不想这样做

SELECT *,
  SUM(
    SELECT SUM(value) 
    FROM tbl 
    WHERE [date] = '2014-08'
    AND ( [type] = 'PROD1' OR [type] = 'PROD3')
  ) AS [SUM_P1+P3],

 SUM(
    SELECT SUM(value) 
    FROM tbl 
    WHERE [date] = '2014-08'
  ) AS [TOTAL_PROD],

 -- Percentage of (PROD1+PROD3)
 (
   SUM(
      SELECT SUM(value) 
      FROM tbl 
      WHERE [date] = '2014-08'
      AND ( [type] = 'PROD1' OR [type] = 'PROD3')
   ) AS [SUM_P1+P3],
   /
   SUM(
      SELECT SUM(value) 
      FROM tbl 
      WHERE [date] = '2014-08'
   )
 ) AS [PCT_P1+P3]

 ...

垂直视图省去了不断重新查询数据库的麻烦。手动将每列添加到SQL查询中不是一个选项,因为表的宽度可能会有所不同。我还要手动写出来感觉笨重(V1 + V2 + V3 + V4 ......)我如何在T-SQL中迭代每一列?是否有像这样的for循环?

DECLARE @mysum int;
for(col in row) {
  SET @mysum = @mysum+col;
}

**如果我有办法检测列数据类型是否为整数,则为点数。

1 个答案:

答案 0 :(得分:2)

我认为您应该回复lc的评论,因为它非常相关,但您可以使用动态SQL实现此目的。

USE mydatabase
DECLARE 
    @table varchar(max) = 'myTable',
    @exec nvarchar(max);

select
    @exec = 'select SUM('+RIGHT(c,LEN(c)-1)+') from '+@table
from (
    select
        '+'+c.name 
    from sys.columns c
    inner join sys.tables t on
        c.object_id = t.object_id
    inner join sys.types ty on
        c.user_type_id = ty.user_type_id
    where
        ty.name in ('int') and
        t.name = PARSENAME(@table,1)
    FOR XML PATH('')
) T (c)
print @exec
exec sp_executesql @exec