2014-06-18 1 views
0

У меня есть таблица MS SQL, которая индексируется по номеру и дате позиции. Мне нужно, чтобы вычислить общую сумму продаж для каждого товара Количество в диапазоне дат (для нескольких диапазонов дат), например, так:Улучшить производительность Sum и Rank в MS SQL

DECLARE @BeginDate DATE = '2014-06-11' 
DECLARE @EndDate DATE = '2014-06-11' 

INSERT INTO @Ranks 
SELECT 
[ItemNumber], 
Sum([Sales]), 
row_number OVER (ORDER BY SUM([Sales]) DESC) AS [Rank] 
WHERE [Date] BETWEEN @BeginDate AND @EndDate 
GROUP BY ItemNumber 

-- Some logic here (not a significant effect on performance) 
DELETE FROM @Ranks 

SET @BeginDate = '2014-05-11' 
INSERT INTO @Ranks 
SELECT 
[ItemNumber], 
Sum([Sales]), 
row_number OVER (ORDER BY SUM([Sales]) DESC) AS [Rank] 
WHERE [Date] BETWEEN @BeginDate AND @EndDate 
GROUP BY ItemNumber 

-- Some logic here (not a significant effect on performance) 
DELETE FROM @Ranks 

-- Query runs several more times, at three, six, and twelve months 

Первый вопрос: есть ли способ, которым я могу реорганизовать это так занимает один запрос? Во-вторых, есть ли лучший способ рассчитать рейтинг по сумме? Моя база данных достаточно велика, и это занимает несколько минут.

ответ

3

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

select t.*, 
     row_number() over (order by sales_1 desc) as rank_1, 
     row_number() over (order by sales_2 desc) as rank_2, 
     row_number() over (order by sales_3 desc) as rank_3, 
     row_number() over (order by sales_4 desc) as rank_4 
from (SELECT ItemNumber, 
      Sum(case when [date] between @BeginDate1 and @EndDate1 then Sales end) as Sales_1, 
      Sum(case when [date] between @BeginDate2 and @EndDate2 then Sales end) as Sales_2, 
      Sum(case when [date] between @BeginDate3 and @EndDate3 then Sales end) as Sales_3, 
      Sum(case when [date] between @BeginDate4 and @EndDate4 then Sales end) as Sales_4 
     WHERE [Date] BETWEEN @BeginDate AND @EndDate 
     GROUP BY ItemNumber 
    ) t 
+3

+1 за большой ответ, но я думаю, что ради ФП в объяснении того, что переменные должны быть связаны было бы полезно. Я не уверен, что обязательно будет очевидно, что вы предоставляете возможность эффективно оценивать ранжирование различных диапазонов дат в одном запросе. Итак, если '@ BeginDate1' месяц назад, а' @ EndDate1' - сегодня, а '@ BeginDate2' - три месяца назад, а' @ EndDate2' - сегодня, то 'rank_1' будет предоставлять рейтинг позиции за последний месяц и' rank_2' обеспечит рейтинг позиции за последние три месяца. Я просто не уверен, что ОП это понял бы. –

+0

Старый запрос занял почти две минуты, это превратило его в 30 секунд - огромное спасибо! – lucrativelucas