2013-08-25 2 views
0

Позвольте мне вкратце описать, что я пытаюсь сделать, если у кого-то есть более элегантный способ решения той же проблемы. Я пытаюсь написать хранимую процедуру, которая рассматривает заказы на продажу в базе данных, обнаруживает, когда один и тот же элемент заказывается одним и тем же клиентом несколько раз, и прогнозирует следующую дату заказа, используя среднее значение предыдущих интервалов между заказами для тот же элемент. Следующий запрос будет служить основой для работы таблицы temp с вероятными курсорами и средними значениями.Улучшение характеристик внешнего применения

Пока запрос у меня есть выглядит следующим образом

SELECT sl.custaccount , 
     sl.itemid , 
     sl.shippingdaterequested , 
     nextdate.shippingdaterequested AS nextshippingdaterequested 
FROM  salesline AS sl 
     OUTER APPLY (SELECT TOP 1 
           sl2.custaccount , 
           sl2.itemid , 
           sl2.shippingdaterequested 
         FROM  salesline AS sl2 
         WHERE  sl2.shippingdaterequested > sl.shippingdaterequested 
           AND sl2.custaccount = sl.custaccount 
           AND sl2.itemid = sl.itemid 
         GROUP BY sl2.custaccount , 
           sl2.itemid , 
           sl2.shippingdaterequested 
         ORDER BY sl2.shippingdaterequested 
        ) AS nextdate 
GROUP BY sl.custaccount , 
     sl.itemid , 
     sl.shippingdaterequested , 
     nextdate.shippingdaterequested 

Этот запрос дает мне строку для каждой продажу линии с колонкой, представляющей в следующий раз этот пункт был заказан по этому клиенту. Если этот столбец равен NULL, я знаю, что запись, в которой я включен, - последний раз.

Основная проблема заключается в том, что этот запрос слишком медленный, он работает нормально, если я иду против одного клиента за один раз, возвращая результаты за секунду, но работа против ~ 100 000 клиентов займет около 27 часов.

Я знаю, что основная проблема заключается в том, что я использую внешний вид, поэтому, вероятно, это делает строку, мучительную обработку строк, но я не уверен в другом способе услышать, что это будет работать быстрее. Есть предположения?

ответ

1

Я думаю, что вы делаете это более сложным, чем это должно быть.
Просто возьмите мин и макс и разделите их на счет

SELECT sl.custaccount , 
    sl.itemid , 
    MAX(sl.shippingdaterequested) AS lastShip , 
    DATEDIFF(dd, MIN(sl.shippingdaterequested), 
      MAX(sl.shippingdaterequested))/COUNT(*) AS interval , 
    DATEADD(dd, 
      DATEDIFF(dd, MIN(sl.shippingdaterequested), 
        MAX(sl.shippingdaterequested))/COUNT(*), 
      MAX(sl.shippingdaterequested)) AS nextShip 
FROM salesline AS sl 
GROUP BY sl.custaccount , 
    sl.itemid 
HAVING COUNT(*) > 1