2

У меня есть эти таблицы:SQL Server Выберите отображение запроса

Таблица 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 является до тех пор, пока сумма не была ниже 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

Если я вас понял правильно, это должно сделать работу. Протестировав производительность по сравнению с вашими, и с установленными здесь значениями, она использует в два раза больше времени, чем ваш запрос на выборку. При использовании в два раза больше данных он использует 1/3: rd времени, необходимого для запуска вашего запроса. Таким образом, это определенно более эффективно, но сколько зависит от общих данных в ваших таблицах, которые вам нужно проверить. (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, тогда просто измените строку ниже на > = 0.

WHERE ((T1.Value+T2.Value) - CA.SumValue) > 0 

EDIT: О, и скрипка не показать все столбцы, принадлежащие к результату. Поэтому проигнорируйте это и попробуйте в SSMS, чтобы получить полный набор результатов.

Смежные вопросы