sum列动态sql

时间:2015-08-27 20:45:59

标签: sql xml dynamic-sql

我在表格中有多个列有一些金额,我想在最后一个总计列中显示所有这些金额的总和。我在sql中有一个表,看起来有点像这样,

A_Amt  B_Amt  C_Amt  D_Amt  E_Amt  F_Amt ... 
------------------------------------------------
 15     20     25     30     35    40       

我写了一个查询

declare @xmlResult xml=
(   
    select  * 
    from    Foo 
    for xml PATH
);

SELECT Nodes.node.value('sum(*[contains(local-name(.), "_Amt")])', 'decimal(15,2)') AS Total
  FROM
  @xmlResult.nodes('//row') as Nodes(node);

但我得到的结果只有一列但我希望结果表中的所有列都像A_amt等。

3 个答案:

答案 0 :(得分:1)

这应该是你需要的,但请注意!你不应该这样做。不应将聚合行与“原始”数据一起提取。在大多数情况下,这是您的UI应该做的事情(或报告......)

fo

答案 1 :(得分:0)

使用Microsoft的系统表是实现动态SQL的一种方式,从而实现您的目标。下面的代码是您想要或至少可以帮助您入门的代码。

我不确定您预期的输出是什么,因此我包含了两个输出。只需使用你想要的那个并丢弃另一个。鉴于你的问题,这可能是结果1。 (Result1或Result2)

!!你必须在执行之前在脚本中写出表名!!

--DISCLAIMER
--It assume you use SQL SERVER 2012. (Probably work on 2005+ with little adjustment)
--It assume data is in a table, (Not a view for example)
--Changing SQL SERVER version may break the code as Microsoft could change "system views".
--I don't remember well, but EXEC may be limited to 4000 characters in dynamic query. (But there is a work around, just look around if you need it)
--So use at your own risk

DECLARE @objectIDTable              INT,
        @AllColumnAdditionStatement NVARCHAR(MAX) = '',
        @TableName                  NVARCHAR(250) = 'WriteYourTableNameHere',--!!!OVERWRITE THE TABLE NAME HERE
        @Query                      NVARCHAR(MAX),
        @AllSumStatement            NVARCHAR(MAX) = ''

SELECT TOP 1    @objectIDTable              = [object_id],
                @AllColumnAdditionStatement = ''
FROM sys.objects
WHERE type_desc = 'USER_TABLE'
AND name = @TableName

SELECT  @AllColumnAdditionStatement = @AllColumnAdditionStatement + 'CONVERT(DECIMAL(18, 4), (CASE WHEN ISNUMERIC(' + name + ') = 1 THEN ISNULL(' + name + ', ''0'') ELSE 0 END))' + ' + ',
        @AllSumStatement            = @AllSumStatement + name + 'Total = SUM(CONVERT(DECIMAL(18, 4), (CASE WHEN ISNUMERIC(' + name + ') = 1 THEN ISNULL(' + name + ', ''0'') ELSE 0 END))), ' + CHAR(10)
FROM sys.columns
WHERE object_id = @objectIDTable
AND name LIKE '%_Amt' --!!!Here is a column filter/selector to sum only column ending with _Amt

SELECT  @AllColumnAdditionStatement = @AllColumnAdditionStatement + '0', --just too lazy to chop off last three char
        @AllSumStatement            = @AllSumStatement + 'Total_ = SUM(' + @AllColumnAdditionStatement + ')' + CHAR(10),
        @Query = 'SELECT *,
                        Total_ = ' + @AllColumnAdditionStatement +'
                 FROM ' + @TableName

PRINT (@Query)
/********************************************************************************************/
EXEC (@Query) --or use sp_execute if you prefer  
--Result1 : addition of all selected columns into total column with all column return as well

/********************************************************************************************/

SELECT @Query = 'SELECT ' + @AllSumStatement + '
                 FROM ' + @TableName

EXEC (@Query) --or use sp_execute if you prefer
--Result2 : Summation of all column individualy and summation of all of them into total column
/********************************************************************************************/

答案 2 :(得分:0)

我认为这就是你要找的,试试这个(用你的表替换spt_values):

 USE MASTER
 GO 

 declare @lsql nvarchar(max)
 declare @lsql2 nvarchar(max)
 declare @yourTable nvarchar(255) = 'spt_values'

 Select @lsql = isnull(@lsql+'+','') + 'Case When ISNUMERIC('+name+') = 1 Then '+name+' else 0 end' from sys.Columns where Object_id = Object_id(@yourTable)

 Print @lsql


 SET @lsql2 = 'Select *, '+@lsql+' as Total_allcolumns From '+@yourTable+''

 Exec(@lsql2)