Как написать запрос, который вычисляет значение, используя предыдущее значение записи? - PullRequest
1 голос
/ 11 октября 2010

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

Рассмотрим таблицу с StartTime & EndTime. Наряду с этими значениями есть 2 различных типа заработной платы: OnDuty & OffDuty.

OnDuty = Все время между StartTime и EndTime.

OffDuty : все время между предыдущим EndTime и текущим StartTime.

Таким образом, чтобы вычислить OffDuty, мы должны взять EndTime последней записи и вычесть StartTime текущей записи.

Пример: * 1 034 * Заработная плата OnDuty = $ 10 / час Заработная плата вне службы = 2 долл. США / час Запись 1: StartTime: 1/1/2010 @ 8:00 AM EndTime: 1/1/2010 @ 6:00 PM Pay = $100 (10 hrs @ $10/hr) Запись 2: StartTime: 1/2/2010 @ 8:00 AM EndTime: 1/2/2010 @ 6:00 PM Pay = $128 (10 hrs @ $10/hr) + (14 hrs @ $2/hr) Запись 3: StartTime: 1/3/2010 @ 8:00 AM EndTime: 1/3/2010 @ 10:00 AM Pay = $48 (2 hrs @ $10/hr) + (14 hrs @ $2/hr) Вы видите образец? Total Pay = $276 (Entry1.Pay + Entry2.Pay + Entry3.Pay) По сути, я спорю о том, будет ли лучше: возложить всю нагрузку на базу данных для расчета этого значения для каждой строки сведений или сохранить EndTime предыдущей записи с каждой строкой (т. Е. PreviousEndTime?) Мне больше нравится вариант 1. Тем не менее, я даже не знаю, как подходить к этому с точки зрения HOW , чтобы сделать это без предварительного создания запроса поиска (примечание: я использую SqlCE). Я в значительной степени полагаюсь на LinqToSql и обеспокоен производительностью с использованием Linq, поскольку могут существовать сотни тысяч этих записей «Entry», которые необходимо рассчитать для обеспечения единственного TotalPay для каждого сотрудника. Выполнять этот поиск в каждом ряду деталей было бы больно! С другой стороны, я чувствую, что с использованием полевого подхода 'PreviousEndTime' потребуется много обслуживания. Пользователь может вернуться и изменить EndTime, и идея обновления следующей записи PreviousEndTime звучит для меня как хак ... Мысли? Идеи? Решения? :)

Ответы [ 3 ]

1 голос
/ 11 октября 2010

Я настоятельно рекомендую опцию «возложить всю нагрузку на базу данных, чтобы рассчитать это значение для каждой строки сведений». Это базы данных материалов (и их языки запросов), предназначенные для.

В Oracle вы бы использовали LEAD и LAG.

http://www.oracle -base.com / article / misc / LagLeadAnalyticFunctions.php

В SQL Server могут быть некоторые обходные пути, см., например:

http://www.rafael -salas.com /2008/05 / t-sql-lead-and-lag-functions.html

Однако не уверен, поддерживается ли это в SQL Server CE.

0 голосов
/ 15 ноября 2010

ОТВЕТ: Просто чтобы проинформировать всех об этом, я прибег к другому подходу ...

Поскольку я использую SQL CE и он не поддерживает виды или функции Lead / Lag, я решил добавить новый столбец PreviousEndTime в свою таблицу. Это был единственный изящный способ, который я смог найти, который позволил мне легко запросить общий расчет на Employee. Это не мое предпочтительное решение, но оно работает нормально для меня ...

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

Вот небольшой фрагмент псевдокода того, что я сейчас делаю:

public decimal GetTotalPay(Employee employee) {
   return (from row in _timeSheet.GetDetailRows(employee.Id)
      select ((row.StartTime - row.PreviousEndTime) * employee.OffDutyWage) +
             ((row.EndTime - row.StartTime) * employee.OnDutyWage)).Sum();
}

Спасибо за все отзывы.

0 голосов
/ 11 октября 2010

Нет необходимости хранить время окончания предыдущего ряда.Вы можете рассчитать разницу с предыдущими строками, используя функцию ранжирования Row_NUMBER () , а затем выполнив самостоятельное соединение.

...