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