【问题标题】:How can we take the sum of each columns in SQL Server without using ;with cte?我们如何在不使用 ;with cte 的情况下获取 SQL Server 中每一列的总和?
【发布时间】:2017-06-07 04:11:22
【问题描述】:

如何将每行的总和乘以第三列中的两行总和?

这里有一个截图来说明:

您可以看到 id 1 的总和为 10,但 id 2 的总和为 10+50 = 60 第三个和是 60+100 = 160 等等。

使用 Cte 对我来说效果很好。我需要没有;with cte 意味着虽然代码我需要总和

示例如下所示

DECLARE @t TABLE(ColumnA INT, ColumnB VARCHAR(50));

INSERT INTO @t 
VALUES (10,'1'), (50,'2'), (100,'3'), (5,'4'), (45,'5');

;WITH cte AS
(
   SELECT ColumnB, SUM(ColumnA) asum
   FROM @t 
   GROUP BY ColumnB
), cteRanked AS
(
   SELECT asum, ColumnB, ROW_NUMBER() OVER(ORDER BY ColumnB) rownum
   FROM cte
) 
SELECT 
    (SELECT SUM(asum) 
     FROM cteRanked c2 
     WHERE c2.rownum <= c1.rownum) AS ColumnA, 
    ColumnB
FROM
    cteRanked c1;

【问题讨论】:

  • 使用 CTE 有什么问题?在 SQL Server 2012+ 中,使用SUM(...) OVER (ORDER BY ...) 可以非常有效地计算运行总数。在以前的版本中,您需要某种形式的相关子查询。
  • @VladimirBaranov 这是一个很长的查询,它是其中的一部分,所以当超过 50000 条记录时,执行查询需要更多时间,
  • 那么,您认为使用 CTE 会使您的查询变慢,对吗? CTE 本身不会影响 SQL Server 中的查询性能。您可以手动将查询重写为一组嵌套的 SELECT,但 SQL Server 已经这样做了。它内联 CTE。如果您追求一个简单的运行总计并且您正在使用 SQL Server 2012+,那么有一种非常有效的方法可以做到这一点。在 SQL Server 2008 中,游标可能比子查询更有效。请说明您使用的 SQL Server 版本。
  • CTE 并不是一个神奇的性能杀手。要求一个不使用 CTE 的解决方案,认为它会解决您的性能问题是错误的。
  • 因为它是一个冗长的查询,它的一部分意味着该查询的 1/20,如果我使用 cte 或 temp 表,它不会影响查询的其余部分,它只会在那个查询中起作用阻止你说不使用 cte 或临时表。

标签: sql-server sql-server-2008 sql-server-2012


【解决方案1】:

一个不需要显式分析函数的选项是使用相关子查询来计算运行总数:

SELECT
    t1.ID,
    t1.Currency,
    (SELECT SUM(t2.Currency) FROM yourTable t2 WHERE t2.ID <= t1.ID) AS Sum
FROM yourTable t1

输出:

演示在这里:

Rextester

【讨论】:

  • 答案是用 cte 写的;我需要不与 cte 一起使用;先生,
  • 我只使用 CTE 代替实际表格。只需将 CTE 替换为您正在使用的实际表即可。正如 cmets 所提到的,使用 CTE 不会对事情产生太大影响。
【解决方案2】:

看来您需要一个简单的运行总计。

在 SQL Server 2012 及更高版本中,有一种简单有效的方法可以计算运行总计。您可以使用SUM(...) OVER (ODER BY ...),如下例所示:

样本数据

DECLARE @t TABLE(ColumnA INT, ColumnB VARCHAR(50));

INSERT INTO @t 
VALUES (10,'1'), (50,'2'), (100,'3'), (5,'4'), (45,'5');

查询

SELECT
    ColumnB
    ,ColumnA
    ,SUM(ColumnA) OVER (ORDER BY ColumnB 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumColumnA
FROM @t
ORDER BY ColumnB;

结果

+---------+---------+------------+
| ColumnB | ColumnA | SumColumnA |
+---------+---------+------------+
|       1 |      10 |         10 |
|       2 |      50 |         60 |
|       3 |     100 |        160 |
|       4 |       5 |        165 |
|       5 |      45 |        210 |
+---------+---------+------------+

对于 SQL Server 2008 及更低版本,您需要像已经使用的那样使用相关子查询或简单游标,如果表很大,这可能会更快。

【讨论】:

  • 如何写成 --->(SUM(ISNULL(A.ColumnA,0) )AS decimal(18,3))--->SUM(ColumnA) OVER (ORDER BY ColumnB ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumColumnA 显示以下错误is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
  • @DonaSusanIssac - 如果您使用的是SUM() OVER (...),那么查询根本不需要(必然)GROUP BY 子句。
  • SELECT EOMONTH (A.TransactDateTime) TransactDateTime, CAST (SUM(ISNULL(A.Profit,0)) AS decimal(18,3)) Profit ,SUM(A.Profit) OVER (ORDER BY A.TransactDateTime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumColumnA FROM CostLedger A WHERE ISNULL(Profit,0)&gt;0 AND YEAR(TransactDatetime)=YEAR(CAST ( '2017-May-01' as Date)) 由此显示Column 'CostLedger.TransactDateTime' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
  • 对不起@DonaSusanIssac,您似乎正试图显着改变问题。我在此答案中的查询根据问题中的示例数据返回正确的结果。如果你有比简单的运行总数更复杂的东西,那么最好再问一个问题并正确解释问题。提供一组良好的相关示例数据,突出问题并说明您想要达到的结果。
  • ok no pblm 我认为我的代码和你的代码一样简单,只是这个Column 'CostLedger.TransactDateTime' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.中的错误@
猜你喜欢
  • 2010-12-27
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
  • 2016-09-24
  • 1970-01-01
  • 2013-02-03
  • 2018-02-19
  • 1970-01-01
相关资源
最近更新 更多