2013-08-30 2 views
0

У нас есть хранимая процедура, которая выполняется против некоторых довольно больших таблиц, а при соединении с большой таблицей также хранится количество записей, соответствующих соответствующему batch_id. Я пытаюсь выяснить, могу ли я улучшить это с помощью функции для подсчета или других средств? Попытка избавиться от вложенного оператора SELECT COUNT (*). Таблица CCTransactions - 1,4 миллиона строк, а BatchItems - 6,6 миллионов строк.подсчет элементов, которые совпадают в выражении select

SELECT a.ItemAuthID, a.FeeAuthID, a.Batch_ID, a.ItemAuthCode, 
     a.FeeAuthCode, b.Amount, b.Fee, 
    (SELECT COUNT(*) FROM BatchItems WHERE Batch_ID = a.Batch_ID) AS BatchCount, 
    ItemBillDate, FeeBillDate, b.AccountNumber, 
    b.Itemcode, ItemAuthToken, FeeAuthToken, 
    cc.ItemMerchant, cc.FeeMerchant 
    FROM CCTransactions a WITH(NOLOCK) 
     INNER JOIN BatchItems b WITH(NOLOCK) 
       ON a.Batch_ID = b.Batch_ID 
     INNER JOIN CCConfig cc WITH(NOLOCK) 
       ON a.ClientCode = cc.ClientCode 
    WHERE ((ItemAuthCode > '' AND ItemBillDate IS NULL) 
       OR (FeeAuthCode > '' AND FeeBillDate IS NULL)) 
       AND TransactionDate BETWEEN DATEADD(d,-7,GETDATE()) 
       AND convert(char(20),getdate(),101) + ' ' + @Cutoff 
    ORDER BY TransactionDate 

ответ

0

Когда СУБД поддерживает WINDOWED агрегатные функции вы можете записать его в

COUNT(*) OVER (PARTITION BY Batch_ID) 

Конечно, это только возвращает количество строк в Batch_ID возвращаемых SELECT. если внутреннее соединение приводит к меньшему количеству строк, это не правильный номер.

Тогда это могло бы быть более эффективным (в зависимости от СУБД), чтобы переписать скалярный подзапрос для объединения:

SELECT a.ItemAuthID, a.FeeAuthID, a.Batch_ID, a.ItemAuthCode, 
     a.FeeAuthCode, b.Amount, b.Fee, 
    dt.BatchCount, 
    ItemBillDate, FeeBillDate, b.AccountNumber, 
    b.Itemcode, ItemAuthToken, FeeAuthToken, 
    cc.ItemMerchant, cc.FeeMerchant 
    FROM CCTransactions a WITH(NOLOCK) 
     INNER JOIN BatchItems b WITH(NOLOCK) 
       ON a.Batch_ID = b.Batch_ID 
     INNER JOIN CCConfig cc WITH(NOLOCK) 
       ON a.ClientCode = cc.ClientCode 
     INNER JOIN 
      ( 
      SELECT BatchCount, COUNT(*) AS BatchCount 
      FROM BatchItems 
      GROUP BY Batch_ID 
     ) AS dt ON a.Batch_ID = dt.Batch_ID 
    WHERE ((ItemAuthCode > '' AND ItemBillDate IS NULL) 
       OR (FeeAuthCode > '' AND FeeBillDate IS NULL)) 
       AND TransactionDate BETWEEN DATEADD(d,-7,GETDATE()) 
       AND convert(CHAR(20),getdate(),101) + ' ' + @Cutoff 
    ORDER BY TransactionDate 
+0

Просто, чтобы добавить это в стандартной версии SQL Server 2005. – joshobud

+0

Я проверил COUNT (*) OVER и, хотя это уменьшило количество просмотров в пределах SET STATISTICS IO ON, это увеличило стоимость поддерева плана. Итак, теперь позвольте мне проверить INNER JOIN подзапроса и посмотреть, как это работает. – joshobud

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