我有这些表格:
表Tb1
(ID Int, CodeID Int, Value Int
)
ID CodeID Value
----------------------
1 1 10
2 1 14
3 1 5
4 1 25
5 2 12
6 2 17
7 2 4
8 2 10
9 2 6
表Tb2
(CodeID Int Value Int
)
CodeID Value
---------------
1 25
2 20
我想查询从Tb1获取记录
SUM(Tb1.Value) <= Tb2.Value
例如,以上记录的结果是:
Tb1.ID Tb1.CodeID Tb1.Value UsedValue Tb2.Value
--------------------------------------------------------
1 1 10 10 25
2 1 14 14 25
3 1 5 1 25
5 2 12 12 20
6 2 17 8 20
我想要一个没有光标的查询。
UsedValue
为Tb1.Value
,直到Tb1.Value
的总和低于Tb2.Value
。
之前我问过这个问题:Select SQL Mapping Query
以下查询是没有光标的查询,但我的数据非常大,而且查询速度很慢。
;WITH Subtotals
AS
(
SELECT
T1.Id, T1.CodeId, SUM(T2.Value) SubTotal
FROM Tb1 T1
JOIN Tb1 T2
ON T1.CodeId = T2.CodeId
AND T1.Id >= T2.Id
GROUP BY T1.Id, T1.CodeId
)
SELECT
S.ID,
S.CodeID,
T1.Value,
CASE WHEN T2.value >= S.Subtotal
THEN T1.value
ELSE T1.value - (S.Subtotal - T2.value)
END UsedValue,
T2.Value T2Value
FROM Subtotals S
JOIN Tb2 T2
ON S.CodeId = T2.CodeId
JOIN Tb1 T1
ON S.Id = T1.Id
WHERE T2.Value >= S.SubTotal - T1.Value
我查找具有上述效果的查询。
提前致谢
答案 0 :(得分:0)
如果我理解正确的话,这应该可以胜任。测试了与您的性能相比的性能,并且使用此处设置的值,它占用的样本查询时间减少了一半。使用两倍以上的数据,它使用1/3:运行样本查询所需的时间。所以它肯定更有效率,但是多少取决于您需要测试的表中的整体数据。 (Get the fiddle example here):
SELECT T1.*
, CASE WHEN CA.SumValue < T2.Value THEN T1.Value
ELSE (T1.Value+T2.Value) - CA.SumValue
END AS UsedValue
, T2.*
FROM Tb1 T1
JOIN Tb2 T2 ON T2.CodeID = T1.CodeID
CROSS APPLY (SELECT SUM(C1.Value) SumValue
FROM Tb1 C1 WHERE C1.CodeID = T1.CodeID AND C1.ID <= T1.ID) CA
WHERE ((T1.Value+T2.Value) - CA.SumValue) > 0
-- Probably a better way to do this, but the beef is above.
AND T1.CodeID IN
(SELECT T2.CodeID
FROM Tb2 T2
JOIN (SELECT CodeID, SUM(VALUE) SumVal
FROM Tb1
GROUP BY CodeID) SRC
ON SRC.CodeID = T2.CodeID AND SRC.SumVal > T2.Value)
评论之后的部分是我所怀疑的,它确保只处理那些Tb1总和超过Tb2值的记录。这不是最有效的方法。
否则上面的部分应该可以正常工作。此外,如果要显示UsedValue为0的结果,因为前一行已达到总和= Tb2.Value,则只需将下面的行更改为&gt; = 0 。
WHERE ((T1.Value+T2.Value) - CA.SumValue) > 0
编辑:哦,小提琴不会显示属于结果的所有列。所以请忽略它,并在SSMS中尝试获取完整的结果集。