SQL 计算客户使用自连接的订单总计 运行

SQL Computing a running total of an order by customer using self-join

所以我知道这已经有点死了,但我真的很挣扎。在工作中,我有 SQL Server 2008,我被要求总共做 运行,所以我没有窗口函数。这意味着我必须按照老派的方式来做,所以为了学习这个,我正在使用 AdventureWorks 2012 数据库并尝试对每个 salesorderidtotaldue 上做一个 运行 总计 salesorderid customerid 在 sales.salesorderheader table。相关栏目是:

salesorderid int not null
customerid int not null
totaldue money not null

这是我目前的情况:

select soh1.salesorderid
, soh1.customerid
, soh1.totaldue
, sum(soh2.totaldue) 'running_total'
from sales.salesorderheader soh1
inner join sales.salesorderheader soh2 on soh1.totaldue <= soh2.totaldue
                                       and soh1.customerid = soh2.customerid
group by soh1.customerid, soh1.salesorderid, soh1.totaldue
order by soh1.customerid, soh1.salesorderid;

我得到以下信息(前 10 行):

salesorderid    customerid  totaldue    runningtotal
43793           11000       3756.989    3756.989
51522           11000       2587.8769   9115.1341
57418           11000       2770.2682   6527.2572
43767           11001       3729.364    3729.364
51493           11001       2674.0227   6403.3867
43736           11002       3756.989    3756.989
51238           11002       2535.964    8966.0143
53237           11002       2673.0613   6430.0503
43701           11003       3756.989    3756.989
51315           11003       2562.4508   8993.9155
57783           11003       2674.4757   6431.4647

我觉得我很接近 - 我注意到当给定 customerid 只有两个销售订单时,运行 总数计算正确。但是,当它达到 3 个或更多时,它就会变得很糟糕。

我查看了 customerid = 11000 的连接中断,以了解为什么第二个和第三个 orderid(51522 和 57418)计算不正确。我运行下面的代码:

select soh1.salesorderid
, soh1.customerid
, soh1.totaldue
, soh2.salesorderid
, soh2.customerid
, soh2.totaldue
from sales.salesorderheader soh1
inner join sales.salesorderheader soh2 on soh1.totaldue <= soh2.totaldue
                                          and soh1.customerid = soh2.customerid
where soh1.customerid = 11000
order by soh1.customerid, soh1.salesorderid;

我明白了:

salesorderid  customerid  totaldue   salesorderid  customerid  totaldue
43793         11000       3756.989   43793         11000       3756.989
51522         11000       2587.8769  43793         11000       3756.989
51522         11000       2587.8769  51522         11000       2587.8769
**51522       11000       2587.8769  57418         11000       2770.2682**
57418         11000       2770.2682  57418         11000       2770.2682
57418         11000       2770.2682  43793         11000       3756.989

我可以在第 4 行看到问题,它引入了我不想要的一行,然后对于 salesorderid 57418,它缺少一行。我怀疑问题出在我的加入上,但我无法弄清楚会带来正确行的逻辑。

我要求能够使用 SQL 2012 或更高版本但没有骰子。请帮忙!

您的自助加入不应该根据客户和销售订单 ID 而不是 totaldue 完成吗?请参阅以下内容:

select soh1.salesorderid
, soh1.customerid
, soh1.totaldue
, sum(soh2.totaldue) 'running_total'
from sales.salesorderheader soh1
inner join sales.salesorderheader soh2 on soh2.salesorderid <= soh1.salesorderid
                                   and soh2.customerid = soh1.customerid
group by soh1.customerid, soh1.salesorderid, soh1.totaldue
order by soh1.customerid, soh1.salesorderid;

或者您可以试试 CTE

;with grouped as
(
    select *, ROW_NUMBER() OVER (PARTITION BY customerid ORDER BY salesorderid) as groupId 
    from sales.salesorderheader
), cte as
(
    select *, totaldue as runningtotal from grouped where groupId = 1
    union all
    select grouped.*, grouped.totaldue + cte.runningtotal
    from grouped inner join cte on 
        grouped.groupId - 1 = cte.groupId 
        and grouped.customerid = cte.customerid
)
select * from cte order by customerid, salesorderid

使用此代码:

select soh1.salesorderid
, soh1.customerid
, soh1.totaldue
,(select  sum(soh2.totaldue) from sales.salesorderheader soh2      
  where soh1.totaldue <= soh2.totaldue 
  and  soh1.customerid = soh2.customerid) as 'Running Totoal'
from sales.salesorderheader soh1
where soh1.customerid = 11000
order by soh1.customerid, soh1.salesorderid