2017-03-21 100 views
3

我发现这个:How to group/rank records based on a changing value of a column?这与我所寻找的相似,但并不像我所需要的那样工作。我如何根据列值分组

基本上,我有一个看起来像这样的数据:

Id   UserId  Type   Amount RunningTotal 
----------- ----------- --------------- -------- ------------- 
2759  750   charge   -50.00 -50.00 
2760  750   charge   -125.00 -175.00 
4308  750   paymentGC  50.00 -125.00 
4309  750   paymentGC  125.00 0.00 
19916  750   charge   -1.00 -1.00 
19917  750   creditRefund 124.00 123.00 
23238  750   paymentCC  50.00 173.00 
23239  750   paymentCC  125.00 298.00 
23240  750   charge   -50.00 248.00 
23241  750   charge   -125.00 123.00 
41300  750   creditRefund 125.00 248.00 
42054  750   paymentCC  50.00 298.00 
42055  750   paymentCC  125.00 423.00 
42056  750   charge   -50.00 373.00 
42057  750   charge   -125.00 248.00 
56983  750   creditRefund 125.00 373.00 
63083  750   paymentCC  50.00 423.00 
63084  750   paymentCC  125.00 548.00 
63085  750   charge   -50.00 498.00 
63086  750   charge   -125.00 373.00 
80829  750   creditRefund 125.00 498.00 

这工作,但我需要的RunningTotal来,每次遇到creditRefund时间重置。我查看了使用OVER(ROWS BETWEEN CURRENT ROW AND x FOLLOWING),但这不起作用,因为它们之间可能有任意数量的行,具体取决于帐户上发生的情况。

所以我需要它看起来更像是这样的:

Id   UserId  Type   Amount RunningTotal 
----------- ----------- --------------- -------- ------------- 
2759  750   charge   -50.00 -50.00 
2760  750   charge   -125.00 -175.00 
4308  750   paymentGC  50.00 -125.00 
4309  750   paymentGC  125.00 0.00 
19916  750   charge   -1.00 -1.00 
19917  750   creditRefund 124.00 123.00 
23238  750   paymentCC  50.00 50.00 
23239  750   paymentCC  125.00 175.00 
23240  750   charge   -50.00 125.00 
23241  750   charge   -125.00 0.00 
41300  750   creditRefund 125.00 125.00 
42054  750   paymentCC  50.00 50.00 
42055  750   paymentCC  125.00 175.00 
42056  750   charge   -50.00 125.00 
42057  750   charge   -125.00 0.00 
56983  750   creditRefund 125.00 125.00 
63083  750   paymentCC  50.00 50.00 
63084  750   paymentCC  125.00 175.00 
63085  750   charge   -50.00 125.00 
63086  750   charge   -125.00 0.00 
80829  750   creditRefund 125.00 125.00 

这里是我到目前为止有:

SELECT Id, UserId, [Type], RunningTotal = SUM(Amount) OVER (ORDER BY t.Id) 
FROM Transactions 
WHERE UserId = @User 

如何做到这一点任何想法?我觉得我需要以某种方式对他们进行分组,以便运行总数重置,并且我可以使用PARTITION BY条款。但是我一直无法让它工作。如果涉及到它,我想我可以在它从db返回后在C#中完成它,但我宁愿不必。

回答

2

使用子查询,以确定各组grp的开始(使用lag()仅开始群一旦当有连续的​​PaymentCC),和另一个,以产生组号sumgrp,然后使用sumgrp作为一个分区RunningTotal

select 
    Id 
    , UserId 
    , Type 
    , Amount 
    , RunningTotal = sum(amount) over (partition by userid, sumgrp order by id) 
    , desired_result 
from (
    select * 
     , sumgrp = sum(grp) over (
      partition by userid 
      order by id 
     ) 
    from (
    select * 
     , grp = (case when type='PaymentCC' 
       and isnull(lag(type) over (
       partition by userid 
       order by id 
       ),'') <> 'PaymentCC' 
      then 1 
      else 0 end) 
    from Transactions 
    ) as g 
) as s 
where UserId = 750 

rextester 演示http://rextester.com/POX67852

回报:

+-------+--------+--------------+---------+--------------+----------------+ 
| Id | UserId |  Type  | Amount | RunningTotal | desired_result | 
+-------+--------+--------------+---------+--------------+----------------+ 
| 2759 | 750 | charge  | -50.00 | -50.00  | -50.00   | 
| 2760 | 750 | charge  | -125.00 | -175.00  | -175.00  | 
| 4308 | 750 | paymentGC | 50.00 | -125.00  | -125.00  | 
| 4309 | 750 | paymentGC | 125.00 | 0.00   | 0.00   | 
| 19916 | 750 | charge  | -1.00 | -1.00  | -1.00   | 
| 19917 | 750 | creditRefund | 124.00 | 123.00  | 123.00   | 
| 23238 | 750 | paymentCC | 50.00 | 50.00  | 50.00   | 
| 23239 | 750 | paymentCC | 125.00 | 175.00  | 175.00   | 
| 23240 | 750 | charge  | -50.00 | 125.00  | 125.00   | 
| 23241 | 750 | charge  | -125.00 | 0.00   | 0.00   | 
| 41300 | 750 | creditRefund | 125.00 | 125.00  | 125.00   | 
| 42054 | 750 | paymentCC | 50.00 | 50.00  | 50.00   | 
| 42055 | 750 | paymentCC | 125.00 | 175.00  | 175.00   | 
| 42056 | 750 | charge  | -50.00 | 125.00  | 125.00   | 
| 42057 | 750 | charge  | -125.00 | 0.00   | 0.00   | 
| 56983 | 750 | creditRefund | 125.00 | 125.00  | 125.00   | 
| 63083 | 750 | paymentCC | 50.00 | 50.00  | 50.00   | 
| 63084 | 750 | paymentCC | 125.00 | 175.00  | 175.00   | 
| 63085 | 750 | charge  | -50.00 | 125.00  | 125.00   | 
| 63086 | 750 | charge  | -125.00 | 0.00   | 0.00   | 
| 80829 | 750 | creditRefund | 125.00 | 125.00  | 125.00   | 
+-------+--------+--------------+---------+--------------+----------------+ 
+0

只见参考'在我的搜索lag'但没有明白这是什么话,所以我甚至不能告诉它是否会使用的情况下重置帮助了解它。谢谢!我会试试这个。 – ahwm

+0

@ahwm乐意帮忙! – SqlZim

0

您可以在运行总计

;with cte as (
select *, sum(amount) over(order by id) RowSum, case when [Type]='creditRefund' Then 1 else 0 end as Num from #yourtable 
) 
, cte2 as (SELECT *, sum(num) over (order by id) ResetFlag from cte) 
select *, sum(case when [Type]='creditRefund' Then 0 else Amount END) over(partition by ResetFlag order by id) from cte2 


create table #yourtable (id int, userid int, type varchar(20), amount float) 

insert into #yourtable (
Id  , UserId , Type  ,  Amount) values 
----------- ----------- --------------- -------- ------------- 
(2759 ,  750  , 'charge  ', -50.00 ) 
,(2760 ,  750  , 'charge  ', -125.00) 
,(4308 ,  750  , 'paymentGC ', 50.00 ) 
,(4309 ,  750  , 'paymentGC ', 125.00 ) 
,(19916 ,  750  , 'charge  ', -1.00 ) 
,(19917 ,  750  , 'creditRefund', 124.00 ) 
,(23238 ,  750  , 'paymentCC ', 50.00 ) 
,(23239 ,  750  , 'paymentCC ', 125.00 ) 
,(23240 ,  750  , 'charge  ', -50.00 ) 
,(23241 ,  750  , 'charge  ', -125.00) 
,(41300 ,  750  , 'creditRefund', 125.00 ) 
,(42054 ,  750  , 'paymentCC ', 50.00 ) 
,(42055 ,  750  , 'paymentCC ', 125.00 ) 
,(42056 ,  750  , 'charge  ', -50.00 ) 
,(42057 ,  750  , 'charge  ', -125.00) 
,(56983 ,  750  , 'creditRefund', 125.00 ) 
,(63083 ,  750  , 'paymentCC ', 50.00 ) 
,(63084 ,  750  , 'paymentCC ', 125.00 ) 
,(63085 ,  750  , 'charge  ', -50.00 ) 
,(63086 ,  750  , 'charge  ', -125.00) 
,(80829 ,  750  , 'creditRefund', 125.00 ) 
相关问题