【问题标题】:Running Total (pre 2012) for more than 1 group超过 1 个组的运行总计(2012 年之前)
【发布时间】:2014-01-09 20:01:10
【问题描述】:

很抱歉再次提出这个话题,我遇到了几个非常相似的有用的现有帖子,但 stackoverflow 不允许我在现有线程上发表评论/问题,因为我是新人(少于 50点)。

无论如何,很多运行总数帖子都非常适合 1 组/运行总数。一旦我引入第二组(我希望运行总数再次从 0 开始),它就会不断将它们相加。

我已经成功使用了古怪的更新、带有递归的 CTE 等……但不适用于多个组。

我正在寻找的基本输出如下所示:

NAME    DATE        DOLLARS     RUNNING
John    1/1/2014    5           5
John    1/2/2014    3           8
John    1/2/2014    4           12
John    1/2/2014    8           20
John    1/3/2014    12          32
Matt    1/1/2014    2           2
Matt    1/2/2014    7           9
Matt    1/3/2014    10          19

我怎样才能做到这一点?提前感谢一堆

以下是我遇到的一些有用的文章:

Partitioning results in a running totals query

Using "Update to a local variable" to calculate Grouped Running Totals

【问题讨论】:

  • 我已经编辑了你的标题。请参阅"Should questions include “tags” in their titles?",其中的共识是“不,他们不应该”。
  • 在您的新问题中,您如何知道同一日期的所有行中的哪一行先出现?
  • 这真的是一个日期时间,所以我已经按日期时间订购了它们 - 谢谢

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


【解决方案1】:

您可以使用相关子查询来做到这一点:

select name, date, dollars,
       (select sum(dollars)
        from table t2
        where t2.name = t.name and
              t2.date <= t.date
       ) as running
from table t;

编辑:

如果您在同一日期有多行,那么您需要引入另一个排序标准。问题中的数据没有其他顺序列(例如 id)。所以,我们可以创建一个:

with t as (
      select t.*, row_number() over (partition by name order by date) as seqnum
      from table t
     )
select name, date, dollars,
       (select sum(dollars)
        from t t2
        where t2.name = t.name and
              t2.seqnum <= t.seqnum
       ) as running
from t t;

唯一的问题是日期中的行将是任意顺序的,甚至可能在查询执行之间发生变化。 SQL 表本质上是无序的,因此您需要一个列来指定排序。

【讨论】:

  • 谢谢这个工作,但是如果同一日期有多行,它会返回我 total 中每一行的 running total那个日期组。我已经编辑了我上面的帖子(对不起)。对您的查询稍作修改可以产生这些结果吗?另外,如果我要引入另一个用于分组的列(例如 COMPANY)——我可以通过这个处理吗?非常感谢!!
  • 再次感谢您的回复!出于某种原因,这仍然给了我每个日期每一行中的日期总数,例如,2014 年 1 月 2 日的 JOHN 在 3 行的 RUNNING 列中得到“20”。
  • 这是非常奇怪的行为。 t 子查询应该有一个在每一行上都不同的序列号。如果您有 id 列,请将其添加到 order by 以使排序稳定 (order by date, id)。
【解决方案2】:

你可以使用OUTER APPLY:

SELECT  A.[NAME],
        A.[DATE],
        A.DOLLARS,
        SUM(B.[DOLLARS]) RUNNING
FROM YourTable A
OUTER APPLY (SELECT *
             FROM YourTable
             WHERE [NAME] = A.[NAME]
             AND [DATE] <= A.[DATE]) B
GROUP BY A.[NAME],
         A.[DATE],
         A.DOLLARS
ORDER BY A.[NAME],
         A.[DATE],
         A.DOLLARS

Here is a demo 供您试用。 结果是:

╔══════╦════════════╦═════════╦═════════╗
║ NAME ║    DATE    ║ DOLLARS ║ RUNNING ║
╠══════╬════════════╬═════════╬═════════╣
║ John ║ 2014-01-01 ║       5 ║       5 ║
║ John ║ 2014-01-02 ║       3 ║       8 ║
║ John ║ 2014-01-03 ║      12 ║      20 ║
║ Matt ║ 2014-01-01 ║       2 ║       2 ║
║ Matt ║ 2014-01-02 ║       7 ║       9 ║
║ Matt ║ 2014-01-03 ║      10 ║      19 ║
╚══════╩════════════╩═════════╩═════════╝

【讨论】:

  • 非常感谢 - 这给了我所要求的结果,但上面的查询产生的结果要快一点!再次感谢
【解决方案3】:

您可以像这样使用ROLLUPCUBE

select name, date, dollars, sum(dollars) running
from table t
group by name, date, dollars with rollup

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多