sql server选择映射查询

时间:2014-01-29 06:23:17

标签: sql sql-server sql-server-2008 sql-server-2008-r2 sql-server-2012

我有这些表格:

Tb1ID 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

Tb2CodeID 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

我想要一个没有光标的查询。

UsedValueTb1.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

我查找具有上述效果的查询。

提前致谢

1 个答案:

答案 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中尝试获取完整的结果集。