Оптимизировать запрос для расчета исторических суммированных значений pr. Дата - PullRequest
0 голосов
/ 26 июня 2011

У меня есть таблица, которая выглядит так:

&ItemNo
&LocationId
&MovementDate
MovementWithinDay
Stock -- the field I need to update with sum of MovementWithinDay for all older records for same item

Поскольку эта таблица содержит более 300 миллионов строк, заполнение поля Stock занимает очень много времени. Каждая строка содержит движения в течение этого дня, и мне нужно рассчитать запас на основе суммы MovementWithinDay для всех записей для этого элемента, которые старше этой записи. Это разовая транзакция, поэтому переход в другую структуру является опцией. Я использовал курсор для просмотра записей, но это было невероятно медленно. Запрос с суммированием всех более старых записей для этого элемента для каждой записи был значительно быстрее, но очень медленным.

Может ли кто-нибудь дать мне указание сделать это в наименьшее количество времени?

Ответы [ 2 ]

1 голос
/ 26 июня 2011

На самом деле нет хорошего ответа для SQL Server.Другие системы БД позволили бы вам написать функцию Analytic SUM () для раздела, оконного по вашей дате, но SQL-сервер этого не делает.

Лучшая ставка, вероятно, - курсор, как ни печально сказать.Взгляните на эту статью SQLTeam.

Проблема с самостоятельным объединением состоит в том, что сервер SQL пересчитывает промежуточную сумму из всех предыдущих строк для каждой строки , вместо этогосохранения итогов и использования его для вычисления промежуточного итога следующей строки.

0 голосов
/ 26 июня 2011

Итак, насколько я понял ваш вопрос, вы хотите использовать суммы MovementWithinDay для каждого &ItemNo.Я полагаю, что для этого можно использовать рекурсивный CTE с рейтингом , если только вы не используете SQL Server 2000 или более раннюю версию.

Вот так может выглядеть запрос:

WITH ranked AS (
  SELECT
    *,
    rank = ROW_NUMBER() OVER (PARTITION BY [&ItemNo] ORDER BY MovementWithinDay)
  FROM
),
cumulated AS (
  SELECT
    [&ItemNo],
    [&LocationId],
    [&MovementDate],
    MovementWithinDay,
    Stock = MovementWithinDay,
    rank
  FROM ranked
  WHERE rank = 1
  UNION ALL
  SELECT
    r.[&ItemNo],
    r.[&LocationId],
    r.[&MovementDate],
    r.MovementWithinDay,
    Stock = c.Stock + r.MovementWithinDay,
    r.rank
  FROM ranked r
    INNER JOIN cumulated c ON r.[&ItemNo] = c.[&ItemNo] AND r.rank = c.rank + 1
)
SELECT
  [&ItemNo],
  [&LocationId],
  [&MovementDate],
  MovementWithinDay,
  Stock = MovementWithinDay
FROM cumulated
...