运行总计,当客户更改时重置(保留现有的行号)- 包括尝试

Pet*_*ock 7 sql-server-2008-r2

我有一个表,其中 RowNumber 是本质。它有一系列客户端,以及该客户端的运行总数 - 每次客户端更改时都会重置。例如

client  rownr   amount  runtotal
Company A   1   1.00    1.00
Company A   2   1.00    2.00  1+1 = 2
Company A   3   5.00    7.00  2+5 = 7
Company B   4   3.00    3.00  Reset Because Customer B <> Previous Row Customer A
Company A   5   1.00    1.00  Reset Because Customer A <> Previous Row Customer B
Company B   6   2.00    2.00  Reset Because Customer B <> Previous Row Customer A
Company B   7   1.00    3.00  2+1 = 3
Company B   8   5.00    8.00  3+5 = 8
Run Code Online (Sandbox Code Playgroud)

我尝试使用分区,但它总是将客户端 A 和客户端 B 组合在一起 - 它删除了行号的关键部分。

请问有什么帮助吗?

 drop table #Checks
CREATE TABLE #Checks
(
  Client VARCHAR(32),
  RowNr int,
  Amount DECIMAL(12,2),
  RunTotal DECIMAL(12,2),
  Part int
);

INSERT #Checks(Client, RowNr, Amount)
          SELECT 'Company A', '1', 1
UNION ALL SELECT 'Company A', '2', 1
UNION ALL SELECT 'Company A', '3', 5
UNION ALL SELECT 'Company B', '4', 3
UNION ALL SELECT 'Company A', '5', 1
UNION ALL SELECT 'Company B', '6', 2
UNION ALL SELECT 'Company B', '7', 1
UNION ALL SELECT 'Company B', '8', 5;

-- gets the first entries per client - these amounts are 
-- the base amounts and the other entries are tallied up

with cte as (
            select
                    c1.client
                  , c1.amount
                  , c1.rowNr
                  , case when c1.client <> c2.client then c1.amount else null end amt
            from #Checks as c1
            left join #Checks as C2 on c1.rownr = (c2.rownr + 1)
  )

select
client
, rownr
, amount
, case when isnull(amt,0) > 0 then amt else total end as runtotal
from cte
cross apply (
                select
                       sum(x.amount) as Total
                from cte as x
                where x.rownr <= cte.rownr and cte.client = x.client
            ) as rt
;

Drop table #Checks
Run Code Online (Sandbox Code Playgroud)

Lam*_*mak 6

这应该做你想做的:

WITH CTE AS
(
    SELECT  *, 
            RN = ROW_NUMBER() OVER(PARTITION BY Client ORDER BY RowNr)
    FROM #Checks
), CTE2 AS
(
    SELECT  *, 
            RN2 = RowNr - RN 
    FROM CTE 
)
SELECT A.Client, A.RowNr, A.Amount, B.RunTotal
FROM CTE2 A
CROSS APPLY (SELECT SUM(Amount) RunTotal
             FROM CTE2
             WHERE Client = A.Client
             AND RN2 = A.RN2
             AND RowNr <= A.RowNr) B
ORDER BY RowNr
Run Code Online (Sandbox Code Playgroud)

结果:

?????????????????????????????????????????
?  Client   ? RowNr ? Amount ? RunTotal ?
?????????????????????????????????????????
? Company A ?     1 ? 1.00   ? 1.00     ?
? Company A ?     2 ? 1.00   ? 2.00     ?
? Company A ?     3 ? 5.00   ? 7.00     ?
? Company B ?     4 ? 3.00   ? 3.00     ?
? Company A ?     5 ? 1.00   ? 1.00     ?
? Company B ?     6 ? 2.00   ? 2.00     ?
? Company B ?     7 ? 1.00   ? 3.00     ?
? Company B ?     8 ? 5.00   ? 8.00     ?
?????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)


Dav*_*ett 4

怎么样:

SELECT c.client, c.rownr, c.amount
     , runtotal = SUM(e.amount)
FROM   #Checks c
JOIN   #Checks e ON e.RowNr <= c.RowNr AND e.Client = c.Client -- row from c (note <= not <) and all earlier rows
LEFT OUTER JOIN -- rows between with different cli
       #Checks d ON d.RowNr < c.RowNr AND d.RowNr > e.RowNr AND d.Client<>c.Client
WHERE d.RowNr IS NULL -- drop where there is a row between the one from c and the one from e with different client
GROUP BY c.client, c.rownr, c.amount
ORDER BY c.rownr
Run Code Online (Sandbox Code Playgroud)

如果客户端上有索引,那么第一个连接在大型数据集上可能会很昂贵(为了提高效率,您需要在客户端、rownr 上有一个索引,在 rownr 上有一个索引(尽管我假设这将是您的 PK,这意味着索引已经))不是很有选择性(如果客户端列中的数据种类及其相对于 rown 的分布意味着基于它的索引不是很有选择性,那么第一个连接将与笛卡尔积一样接近没有机会)。