2013-12-06 5 views
0

У меня есть таблица со всеми записями продаж (по документу/элементу). Мне нужен отчет с некоторыми индикаторами по позиции, но только для документов VB (тип документа). Однако мне нужны некоторые показатели, такие как максимальное количество в день/элемент, что заставляет меня к другому запросу, но это сгруппировано по дням. Проблема в том, что я получаю очень медленный запрос. В общей сложности 4700000 запрос занял 4 часа.Оптимизация запросов

Можно ли оптимизировать этот запрос? Наверное, не сделал это наилучшим образом ...

SELECT std.ItemID AS [REF.], SUM(std.Quantity) AS [TOTAL QTY] 
, MAX(t1.Qty) AS [MAX QTY BY DAY] 
, COUNT(DISTINCT(std.CreateDate)) AS [SALES DAYS] 
, DATEDIFF(DAY,MIN(std.CreateDate),MAX(std.CreateDate))+1 AS [CALENDAR DAYS] 
FROM SaleTransactionDetails std 
INNER JOIN (
    SELECT CreateDate, ItemID, SUM(Quantity) AS [Qty] 
    FROM SaleTransactionDetails 
    WHERE TransDocument = 'VB' AND CreateDate > '2012-12-15' 
    GROUP BY CreateDate, ItemID) t1 
    ON std.ItemID = t1.ItemID 
WHERE std.TransDocument = 'VB' AND std.CreateDate > '2012-12-15' 
GROUP BY std.ItemID 

Буду признателен за любую помощь. Спасибо вам всем!

+4

Этот вопрос не соответствует теме, потому что речь идет о просмотре кода. (Попробуйте codereview.stackexchange.com) – Stijn

+2

Зависит от индексов и т. Д. –

ответ

1

Вам не нужно ссылаться на таблицу дважды, чтобы сделать это, вы можете получить все, что вам нужно от одного сканирования:

SELECT [REF.] = std.ItemID, 
     [Total Quantity] = SUM(std.Quantity), 
     [Max Qty By Day] = MAX(std.Quantity), 
     [Sales Days] = COUNT(std.CreateDate), 
     [Calendar Days] = DATEDIFF(DAY, MIN(std.CreateDate), MAX(std.CreateDate)) + 1 
FROM ( SELECT std.CreateDate, 
        std.ItemID, 
        Quantity = SUM(std.Quantity) 
      FROM SaleTransactionDetails std 
      WHERE std.TransDocument = 'VB' 
      AND  std.CreateDate > '2012-12-15' 
      GROUP BY std.CreateDate, std.ItemID 
     ) std 
GROUP BY std.ItemID; 

Однако более важным фактором в вашем Perfomance будет как таблица индексируются. Лучший способ узнать, какой индекс нужен, - запустить запрос с включенной опцией «Экран фактического исполнения», а затем SSMS предложит индекс для улучшения запроса. Я бы предположил, что следующее filtered index улучшит производительность

CREATE NONCLUSTERED INDEX IX_SaleTransactionDetails_ItemID_CreateDate 
    ON SaleTransactionDetails (ItemID, CreateDate) 
    INCLUDE (Quantity) 
    WHERE TransDocument = 'VB'; 
+0

Индекс в столбце «CreateDate» может помочь больше, в зависимости от распространения записей. –

+0

@ Colin'tHart Я был бы невероятно удивлен, если бы это помогло больше, дополнительный сортировка, требуемая для ItemID во время агрегации потока из-за того, что ItemID не был в индексе, будет огромными накладными расходами, независимо от распространения данных. – GarethD

+0

@ Colin'tHart Я установил [быстрый скрипт SQL] (http://sqlfiddle.com/#!3/3cd0f/1), если вы проверите планы выполнения для первого и второго запросов (вторая заставит использование индекса только для 'createDate'), вы увидите, что дополнительная операция сортировки оценивается в 78% от общей стоимости запроса. – GarethD

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