在多列上运行总计

时间:2015-11-19 04:48:56

标签: sql-server sql-server-2008 tsql running-total

我有一张这样的桌子。

Date               Item               BuyItem
20150101           Mouse              10
20150101           Keyboard           100
20150202           Mouse              20
20150202           Keyboard           200

我想这样查询。

Date               Item               RunningTotal
20150101           Mouse              10
20150202           Mouse              30
20150101           Keyboard           100
20150202           Keyboard           300
我怎么能这样做? 递归CTE绑定在一个正在运行的列上,如Date,对吗? 现在我有一个正在运行的列,Date和另一个分组列Item。 请帮助我!

4 个答案:

答案 0 :(得分:2)

尝试使用Cross ApplyCorrelated sub-query

;with cte as
(
select 
 * from
 (VALUES (20150101,'Mouse',10),
               (20150101,'Keyboard',100),
               (20150202,'Mouse',20),
               (20150202,'Keyboard',200) )tc(Date, Item, BuyItem) 
)
SELECT *
FROM   cte a
       CROSS apply(SELECT Sum(BuyItem) AS running_total
                   FROM   cte b
                   WHERE  a.Item = b.Item
                          AND a.Date >= b.Date) cs 

<强>结果:

Date        Item        BuyItem running_total
--------    --------    ------- -------------
20150101    Mouse       10      10
20150202    Mouse       20      30
20150101    Keyboard    100     100
20150202    Keyboard    200     300

Recursive CTE方法:

;WITH cte
     AS (SELECT Row_number()OVER(partition BY Item
                    ORDER BY date ) AS rn,*
         FROM   (VALUES (20150101,'Mouse',10),
                        (20150101,'Keyboard',100),
                        (20150202,'Mouse',20),
                        (20150202,'Keyboard',200) )tc(Date, Item, BuyItem)),
     CTE_RunningTotal
     AS (SELECT Date,Item,BuyItem,BuyItem AS running_total,rn
         FROM   cte
         WHERE  rn = 1
         UNION ALL
         SELECT T.Date,T.Item,t.BuyItem,
                T.BuyItem + C.running_total AS running_total,
                t.rn
         FROM   CTE_RunningTotal AS C
                INNER JOIN cte AS T
                        ON T.Item = c.Item
                           AND t.rn = C.rn + 1)
SELECT Date,
       Item,
       BuyItem,
       running_total
FROM   CTE_RunningTotal AS C

最好将您的服务器更新为2012,这可以使用sum() over(order by)方法来计算比这些方法快得多的运行总计

答案 1 :(得分:1)

利用窗口功能。在SQL 2012 +

DECLARE @Items TABLE
(
DATE NVARCHAR(MAX),
Item NVARCHAR(MAX),
BuyItem int
)

INSERT INTO @Items(DATE, Item, BuyItem) VALUES('20150101', 'Mouse', 10)
INSERT INTO @Items(DATE, Item, BuyItem) VALUES('20150101', 'Keyboard', 100)
INSERT INTO @Items(DATE, Item, BuyItem) VALUES('20150202', 'Mouse', 20)
INSERT INTO @Items(DATE, Item, BuyItem) VALUES('20150202', 'Keyboard', 200)

SELECT DATE, Item, SUM(BuyItem) OVER (PARTITION BY Item ORDER BY BuyItem) AS RunningTotal FROM @Items ORDER BY Item DESC

这是运行以上查询的输出。

20150101    Mouse       10
20150202    Mouse       30
20150101    Keyboard    100
20150202    Keyboard    300

答案 2 :(得分:0)

在聚合函数中,使用运行总计,使用Window函数是非常好的性能

在SQL 2012 +中:

SELECT *,
   SUM() OVER(PARTITION BY Item, ORDER BY Date) AS RunningTotal
FROM
Your_Table
ORDER BY Item DESC

比添加窗口框架时更快:

SELECT *,
   SUM() OVER(PARTITION BY Item, ORDER BY Date ROWS UNBOUNDED PRECEDING) AS RunningTotal
FROM
Your_Table
ORDER BY Item DESC

答案 3 :(得分:0)

SELECT Date,
       item,
       running_total
FROM   #yourtable a
       CROSS apply(SELECT Sum(BuyItem) AS running_total
                   FROM   #yourtable b
                   WHERE  a.Item = b.Item
                          AND a.Date >= b.Date) ca
ORDER  BY BuyItem