我们有一个交易表,其结构如下:
TranxID int (PK and Identity field)
ItemID int
TranxDate datetime
TranxAmt money
TranxAmt可以是正数或负数,因此该字段的运行总计(对于任何ItemID)将随着时间的推移而上下移动。获得当前总数显然很简单,但我所追求的是获得运行总计和TranxDate最高值的高效方法。请注意,TranxDate不是唯一的,并且由于某些回溯,ID字段不一定与给定项目的TranxDate序列相同。
目前我们正在做这样的事情(@tblTranx是一个只包含给定Item的事务的表变量):
SELECT Top 1 @HighestTotal = z.TotalToDate, @DateHighest = z.TranxDate
FROM
(SELECT a.TranxDate, a.TranxID, Sum(b.TranxAmt) AS TotalToDate
FROM @tblTranx AS a
INNER JOIN @tblTranx AS b ON a.TranxDate >= b.TranxDate
GROUP BY a.TranxDate, a.TranxID) AS z
ORDER BY z.TotalToDate DESC
(TranxID分组消除了重复日期值导致的问题)
对于一个Item,当发生这种情况时,它给出了HighestTotal和TranxDate。我们只是在应用程序更新相关条目并将值记录在另一个表中以用于报告时,而不是为数万个条目动态运行此值。
问题是,这可以以更好的方式完成,这样我们就可以动态计算出这些值(同时为多个项目)而不会陷入RBAR陷阱(某些ItemID有数百个条目)。如果是这样,那么是否可以对其进行调整以获得事务子集的最高值(基于上面未包括的TransactionTypeID)。我目前正在使用SQL Server 2000,但SQL Server 2008将很快接管,因此可以使用任何SQL Server技巧。
答案 0 :(得分:3)
SQL Server
计算跑步总数很糟糕。
以下是您的查询的解决方案(按日期分组):
WITH q AS
(
SELECT TranxDate, SUM(TranxAmt) AS TranxSum
FROM t_transaction
GROUP BY
TranxDate
),
m (TranxDate, TranxSum) AS
(
SELECT MIN(TranxDate), SUM(TranxAmt)
FROM (
SELECT TOP 1 WITH TIES *
FROM t_transaction
ORDER BY
TranxDate
) q
UNION ALL
SELECT DATEADD(day, 1, m.TranxDate),
m.TranxSum + q.TranxSum
FROM m
CROSS APPLY
(
SELECT TranxSum
FROM q
WHERE q.TranxDate = DATEADD(day, 1, m.TranxDate)
) q
WHERE m.TranxDate <= GETDATE()
)
SELECT TOP 1 *
FROM m
ORDER BY
TranxSum DESC
OPTION (MAXRECURSION 0)
您需要在TranxDate
上设置索引才能使其快速运行。