表格中有3列 - 客户ID,订单号,付款日期和付款。当用户进行付款时,它会使用客户ID记录数据,增加订单号(因此第一笔付款为1,第二笔付款为2等),并且具有日期和付款金额。
我只想查询所有首笔付款,直到总付款金额达到阈值/条件100为止。
首先,我尝试使用sum()来查看是否有些东西会神奇地出现在我的脑海中 - 但总数是我知道怎么做的:
select CustomerID, Order, sum(Payment) as FirstFullPayment
from #temp
group by CustomerID
然后我尝试制作两个不同的临时表 - 未完成付款的#up和完成付款的#fp。我的想法是,我可以将已确认的> 100付款放入#fp,并将已确认的未完成付款放入#up中,如下所示:
select * into #fp
from #temp
where Order = 1 and Payment >= 100
select * into #up
from #temp
where Order = 1 and Payment < 100
然后我可以按顺序加入#up和#temp,其中Order = 2,3,4等,在#up中添加付款,直到它们是&gt; = 100,然后将它们插入#fp
唯一的问题是我知道这是一个非常糟糕和迂回的方法,必须有一个更好,更简单的方法来做到这一点!提前谢谢!
答案 0 :(得分:3)
您可以使用运行总和并按您的条件选择行:&lt; = 100
select top 1 * from
(
select CustomerID,
(
SELECT SUM(b.payment)
FROM #temp b
WHERE a.customerid=b.customerID and b.[order] <= a.[order]) as FirstFullPayment
from #temp a
--where customerid=yourCustomerId
)runningsums
where runningsums.FirstFullPayment<=100
order by runningsums.FirstFullPayment desc
答案 1 :(得分:1)
我假设没有任何付款可以是负数,因此累积金额也将是一个增加的系列(单调)。如果您想要累计总数和订单数超过阈值,这是实现此目的的一种方法:
select CustomerID, min(OrderNumber), min(CumulativePayments)
from
(
select
CustomerID, OrderNumber,
(
select sum(t2.Payment) from T t2
where t2.CustomerID = t.CustomerID and t2.OrderNumber <= t.OrderNumber
) as CumulativePayments
from T t
) cp
where CumulativePayments >= 100
group by CustomerID
编辑:如果您需要所有数据和行最多阈值点:
select * from T t
where OrderNumber <=
(
select min(OrderNumber)
from
(
select
OrderNumber,
(
select sum(t3.Payment) from T t3
where t3.CustomerID = t2.CustomerID and t3.OrderNumber <= t2.OrderNumber
) as CumulativePayments
from T t2
where t2.CustomerID = t.CustomerID
) cp
where CumulativePayments >= 100
)
这些方法不依赖row_number()
或sum() over (...)
或top n...order by
。
答案 2 :(得分:1)
这是使用公共表表达式的另一种方法(随SQL 2005引入):
;WITH cteBaseline
as (-- For each customer, for each order, get sum of payments for all
-- orders less than or equal to "this" order, where the total is
-- within the desired range
select
te.CustomerId
,te.Order
,sum(subset.Payment) TotalPayment
from #temp te
inner join #temp subset
on subset.CustomerId <= te.CustomerId
group by
te.CustomerId
,te.Order
having sum(subset.Payment) < 100 -- Make this a parameter to control the "breakpoint"
)
-- Get the "last" row
select
cte.CustomerId
,cte.Order
,cte.TotalPayment
from cteBaseline cte
inner join (-- get the "last" row, the one with the largest TotalPayment
select
CustomerId
,max(Order)
from cteBaseline
group by CustomerId) xx
on xx.CustomerId = cte.CustomerId
and xx.Order = cte.Order
您想要仔细检查语法。此外,根据表格大小和索引,这可能表现不佳,因为有很多加入。