2013-03-04 4 views
1

У меня есть следующая таблица, содержащая данные о продажах продукта из группы сетевых магазинов. Данные большие и уродливые, но единственный способ получить его из магазинов. Для информации таблица в настоящее время содержит 22 миллиона записей, которые растут примерно на 300 тыс. В день, и этот темп роста будет экспоненциально увеличиваться примерно на 100% ежемесячно.SQL Multiple Join/Sums on Product table

Store_Purchases(
[ID] [int] IDENTITY(1,1) NOT NULL, 
[storecode] [int] NULL, 
[dtDatum] [datetime] NULL, 
[Barcode] [varchar](50) NULL, 
[Desc] [varchar](100) NULL, 
[qty] [int] NULL, 
[amount] [money] NULL, 
[TillslipID] [int] NULL) 

Запрос мне нужно вытащить из этого топ 500 продуктов по сумме всех продаж по диапазону дат. Для каждого из этих продуктов мне нужно показать штрих-код, описание, сумму проданного количества, сумму суммы продажи, затем также количество показов, на которых был включен продукт, и, наконец, общая сумма всех продуктов.

До сих пор мне удалось придумать следующее. Этот запрос занимает 2 м20 для выполнения на моем сервере, и я думаю, что значение «Сумма корзины» неверно. Я хотел бы знать, есть ли лучший способ сделать это в одном запросе или даже в хранимой процедуре.

SELECT 
    a.Barcode, 
    a.Desc, 
    SUM(b.amount) 'Basket SUM', 
    COUNT(distinct b.TillslipID) 'Basket Count', 
    Sales.Count, 
    Sales.Amount 
FROM Store_Purchases b WITH (NOLOCK), 
Store_Purchases a WITH (NOLOCK), 
(
    SELECT 
    top 500 Barcode, 
    sum(qty) "Count", 
    SUM(amount) "Amount" 
    FROM Store_Purchases WITH (NOLOCK) 
    WHERE (storecode = 30143) 
    AND dtDatum BETWEEN '1-Feb-2013 00:00:00' AND '28-Feb-2013 23:59:59' 
    GROUP BY Barcode 
    ORDER BY SUM(amount) DESC 
) AS Sales 
WHERE (a.storecode = 30143) 
AND a.dtDatum BETWEEN '1-Feb-2013 00:00:00' AND '28-Feb-2013 23:59:59' 
AND a.Barcode = Sales.Barcode 
AND a.TillslipID = b.TillslipID 
AND a.storecode = b.storecode 
AND b.dtDatum BETWEEN '1-Feb-2013 00:00:00' AND '28-Feb-2013 23:59:59' 
GROUP BY a.Barcode, a.Desc, Sales.Count, Sales.Amount 
ORDER BYSales.Count DESC 

Любая помощь будет принята с благодарностью. Благодарю.

+0

Разница в поле TillslipID добавляет 2 минуты к времени выполнения запроса, но я не мог придумать другого способа сделать это. – mutantskin

ответ

0
select top 500 Barcode, [Desc], sum([Count]) as [Count], sum([Amount]) as Amount, sum(BasketSum) as [Basket Sum], count(TillslipID) as [Basket Count] 
from (
    select Barcode, [Desc], TillslipID, [Count], [Amount], sum(Amount) over (partition by TillSlipID) as BasketSum 
    from (
     select TillslipID, Barcode, [Desc], sum(qty) as [Count], sum(amount) as [Amount] 
     FROM ez_Sparbuck_Products p 
     WHERE (storecode = 30143) and dtDatum between '1-Feb-2013 00:00:00' and '28-Feb-2013 23:59:59' 
     group by Barcode, [Desc], TillslipID, 
    ) t 
) t 
group by Barcode, [Desc] 

Это делает предположение о том, что штрих-код не имеет два [Desc] с, что, учитывая результат, который вы пытаетесь достичь, по-видимому, имеет место. Если это не так, этот же запрос можно было бы изменить, чтобы использовать partition by Barcode и distinct.

Для томов данных, которые вы делаете это, я думаю, вам понадобится ваш кластеризованный индекс на dtDatum, а может быть, какое-то разбиение на storecode.

+0

Спасибо, это очень близко. Я должен был добавить «WHERE (storecode = 30143) и dtDatum между« 1-Feb-2013 00:00:00 »и« 28 -Feb-2013 23:59:59 ») во внутреннюю часть присоединения, и теперь она тянет 500 строк за 1 сек. Единственная проблема заключается в том, что поле «Сумма корзины» не приводит к правильному значению. Хотя это близко. – mutantskin

+0

При втором осмотре счетчик корзины также выключен. Пожалуйста, примите во внимание, что может быть более одной записи для одного и того же продукта с тем же TillSlipID. – mutantskin

+0

ОК, см. Обновленный ответ на «Корзина», это лучше? Можете ли вы дать точное определение корзины SUM? Я прочитал его как сумму суммы для всех корзин, содержащих этот штрих-код. – muhmud