使用SQL Server 2008 R2,我有一个视图vwBASECustomerTransactions,其中包含一个事务列表,它们汇总了每天每种事务类型的聚合数据:
Create View vwBASECustomerTransactions AS
Select CustomerID, 0 as TransType, Sum(Amount) as TransAmount, Cast(ChargeDate as Date) as TransDate
from Charge
Group by CustomerID, Cast(ChargeDate as Date)
UNION ALL
Select CustomerID, 1, Sum(Amount), Cast(AdjustDate as Date)
from Adjustment
Group by CustomerID, Cast(AdjustDate as Date)
UNION ALL
Select CustomerID, 2, Sum(Amount), Cast(PaymentDate as Date)
from Payment
Group by CustomerID, Cast(PaymentDate as Date)
结果是:
CustomerID | TransType | TransAmount | TransDate
-----------------------------------------------
120 | 0 | 100 | 1/1/2014
120 | 2 | -100 | 1/1/2014
120 | 0 | 50 | 17/2/2014
有超过200,000个CustomerID和大约200万个交易。
我需要找到每个CustomerID的余额最大的日期。
我创建了一组视图,其中包含在每个交易日期计算的余额,它只是简单地将交易汇总到该时间点,但速度非常慢:
--Get the Net Daily Change
Create View vwBASECustomerNetBalChange as
Select CustomerID, TransDate, Sum(TransAmount) as Amount
from vwBASECustomerTransactions
Group by CustomerID, TransDate
--Get the Running Balance for any date
Create View vwRPTCustomerDailyBalance as
Select *, (Select Sum(Amount) from vwBASECustomerNetBalChange Where TransDate <= a.TransDate and CustomerID = a.CustomerID ) as Balance
from vwBASECustomerNetBalChange
--Get the Max Balance for any Customer (join back to get date)
--Takes > 10 minutes to run
Select CustomerID, Max(Balance)
from vwRPTCustomerDailyBalance
group by CustomerID
有更好,更有效的方法吗?
答案 0 :(得分:1)
你可以试试这个,看它是否比你所看到的更好。在我最终弄清楚它到底是什么时,你试图这样做与你的版本非常相似:(第一个子查询中的联盟将基本上选择不同的值,这将减慢速度。
SELECT DistinctDays.CustomerID,DistinctDays.TransDate,TotalAmount=SUM(TotalAmount.TransAmount)
FROM
(
Select CustomerID, Cast(ChargeDate as Date) as TransDate from Charge
UNION
Select CustomerID, Cast(AdjustDate as Date) from Adjustment
UNION
Select CustomerID, Cast(PaymentDate as Date) from Payment
)AS DistinctDays
INNER JOIN
(
Select CustomerID, Amount as TransAmount, ChargeDate as TransDate from Charge
UNION ALL
Select CustomerID, Amount, AdjustDate from Adjustment
UNION ALL
Select CustomerID,Amount, PaymentDate from Payment
)
AS TotalAmount ON TotalAmount.CustomerID=DistinctDays.CustomerID AND TotalAmount.TransDate<=DistinctDays.TransDate
GROUP BY DistinctDays.CustomerID,DistinctDays.TransDate
ORDER BY DistinctDays.CustomerID,DistinctDays.TransDate
答案 1 :(得分:0)
评论太长了。
不幸的是,SQL Server 2008并不直接支持累积总和。但我怀疑,可能有更有效的方法来获得你想要的东西。 SQL Server 2012 支持累积总和。
我认为最好的方法是使用临时表而不是视图。在临时表上,您可以添加CustomerId, date
的索引,这对相关子查询应该是一个很大的帮助。
另一种方法是在视图内的表级执行累积和。这可以利用表级别的索引。但是,我认为临时表方法可能是最好的解决方案。
答案 2 :(得分:0)
这会给你带来结果吗?它使用直接表连接。
SELECT * FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY CUSTOMER_ID ORDER BY BALANCE DESC) AS ID,*
FROM
(SELECT A.CUSTOMERID,A.TRANSDATE,SUM(A.AMOUNT+B.AMOUNT+C.AMOUNT) AS BALANCE
FROM CHARGE A
JOIN ADJUSTMENT B
ON A.CUSTOMERID=B.CUSTOMERID
AND CAST(A.TRANSDATE AS DATE)= CAST(A.TRANSDATE AS DATE)
JOIN PAYMENT C
ON A.CUSTOMERID=C.CUSTOMERID
AND CAST(A.TRANSDATE AS DATE)= CAST(C.TRANSDATE AS DATE)
GROUP BY A.CUSTOMERID,A.TRANSDATE)
)STAB
WHERE ID=1
我们可以根据需要使用条件。由于我不了解运行平衡,我跳过了where子句。
答案 3 :(得分:0)