T-SQL:列值相加的高效方式

T-SQL: Efficient way to add up column values

现在我确定有人问过这个问题,并且在这里得到了很好的回答。但是,我找不到答案,因为涉及到很多关键字。
我基本上想替换以下形式的 table:

Type   amount   param   note
7      2        str1    NULL
42     12       str2    NULL
128    7        str3    samplenote
42     12       NULL    NULL
101    4        str4    NULL
42     12       NULL    NULL
7      1        str1    samplenote
128    2        str5    NULL

table 喜欢:

Type   amount   param   note
7      3        str1    combined
42     36       NULL    combined
128    9        NULL    combined
101    4        str4    combined

换句话说,我试图在为所有 "unclear" 字段声明 param = NULL 的同时,根据其类型来总结金额参数。 (当组合类型的param值有多个不同的内容时,param应该为NULL;否则,param应该有原始内容。)

凭借我的 python 背景,我使用 for 循环方法解决了这个任务,遍历类型,为每种类型添加一个新行,其中包含总金额和注释 = 'combined',以然后删除剩余的行(见下文)。我敢肯定,必须有一种更有效的方法来处理一些 JOIN 语句。但是那会是什么样子呢?

仅供参考,这是我正在研究的解决方案(尚未运行!):

/*** dbo.sourcetable holds all possible Type values ***/
CREATE PROCEDURE [sumup]

AS
BEGIN

DECLARE @i int = (SELECT TOP (1) Type FROM [dbo].[sourcetable] ORDER BY Type)
DECLARE @MaxType int = (SELECT TOP (1) Type FROM [dbo].[sourcetable] ORDER BY Type DESC)

DECLARE @sum int

BEGIN TRY
    WHILE @i <= @MaxType
    BEGIN
        IF EXISTS (SELECT * FROM [dbo].[worktable] WHERE Type = @i)
        BEGIN
            SET @sum = (SELECT SUM(amount) FROM [dbo].[worktable] WHERE Type = @i)

            BEGIN
                WITH cte AS (SELECT * FROM [dbo].[worktable] WHERE Type = @i)
                INSERT INTO [dbo].[worktable]
                    ([Type]
                    ,[amount]
                    ,[param]
                    ,[note]
                SELECT
                     cte.Type
                    ,@sum
                    ,cte.param
                    ,'combined'
                FROM cte
            END

            DELETE FROM [dbo].[worktable] WHERE Type = @i AND ISNULL([note],'') <> 'combined'

        END
        SET @i = @i + 1
    END

END TRY
BEGIN CATCH 

    -- some errorlogging code

END CATCH

END

GO

我是通过键盘这样做的,但这可能会奏效或接近你想要的效果

Select type , amount , iif( dc=1,p,null) param, 'combined' note
from
(
   Select type, sum(amount) amount, 
          count(distinct Param) dc,max(Param) p
   From ....
   Group by type
) x

这是一个可能的解决方案:

declare @tbl as table (
    type int
    ,amount int
    ,param varchar(15)
    ,note varchar(15)
)

insert into @tbl values (7,2,'str1',NULL)
insert into @tbl values (42,12,'str2',NULL)
insert into @tbl values (128,7,'str3','samplenote')
insert into @tbl values (42,12,NULL,NULL)
insert into @tbl values (101,4,'str4',NULL)
insert into @tbl values (42,12,NULL,NULL)
insert into @tbl values (7,1,'str1','samplenote')
insert into @tbl values (128,2,'str5',NULL)

;WITH CTE AS (
    SELECT
        type
        ,SUM(AMOUNT) AS amount
        ,COUNT(DISTINCT ISNULL(param, 'dummy value')) AS ParamNo
        ,MAX(Param) AS Param
    FROM @tbl
    GROUP BY type
) SELECT
    type
    ,amount
    ,CASE WHEN ParamNo = 1 THEN Param ELSE NULL END AS Param
    ,'combined' AS note
FROM CTE

这应该有效:

Select Type, sum(amount) as amount, count(distinct param)
, case when count(distinct param) = 1  then max(param) end as param,  
'Combined' as note
From 
mytable
Group By Type

这可以通过单个 select 语句实现。

如果您要求 combined 标志仅适用于合并了多行的地方,请添加另一个 case 表达式检查合并行的 count(1) 结果或 count(distinct param) 对于唯一的 param 组合值:

declare @t as table(type int, amount int, param varchar(15), note varchar(15));
insert into @t values (7,2,'str1',NULL),(42,12,'str2',NULL),(128,7,'str3','samplenote'),(42,12,NULL,NULL),(101,4,'str4',NULL),(42,12,NULL,NULL),(7,1,'str1','samplenote'),(128,2,'str5',NULL);

select type
      ,sum(amount) as amount
      ,case when count(distinct isnull(param,'')) = 1
            then max(param)
            else null
            end as param
      ,'combined' as note
from @t
group by type
order by type;

输出:

+------+--------+-------+----------+
| type | amount | param |   note   |
+------+--------+-------+----------+
|    7 |      3 | str1  | combined |
|   42 |     36 | NULL  | combined |
|  101 |      4 | str4  | combined |
|  128 |      9 | NULL  | combined |
+------+--------+-------+----------+