SQL 计算客户使用自连接的订单总计 运行
SQL Computing a running total of an order by customer using self-join
所以我知道这已经有点死了,但我真的很挣扎。在工作中,我有 SQL Server 2008,我被要求总共做 运行,所以我没有窗口函数。这意味着我必须按照老派的方式来做,所以为了学习这个,我正在使用 AdventureWorks 2012 数据库并尝试对每个 salesorderid
在 totaldue
上做一个 运行 总计 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
所以我知道这已经有点死了,但我真的很挣扎。在工作中,我有 SQL Server 2008,我被要求总共做 运行,所以我没有窗口函数。这意味着我必须按照老派的方式来做,所以为了学习这个,我正在使用 AdventureWorks 2012 数据库并尝试对每个 salesorderid
在 totaldue
上做一个 运行 总计 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