2015-12-16 6 views
3

Я использую SQL Server 2014. Когда я тестировал свой код, я заметил проблему. Предположим, что максимальный час составляет 80 часов.Условный SUM в SQL Server 2014

SELECT  
    lsm.EmployeeName, 
    pd.absenceDate, 
    pd.amountInDays * 8 AS [HoursReported], 
    pd.status, 
    (SUM(CASE WHEN pd.[status]='App' THEN (pd.amountInDays * 8) 
       ELSE 0 END) OVER (partition by lsm.[EmployeeName] order by pd.absenceDate)) AS [TotalUsedHours] 
      (@maxPSHours) - (sum(
       CASE WHEN pd.[status]='App' THEN (pd.amountInDays * 8) 
        ELSE 0 END) 
      over (
       partition by lsm.[EmployeeName] order by pd.absenceDate)) AS [TotalRemainingHours] 
FROM  
    [LocationStaffMembers] lsm 
INNER JOIN 
    [PersonalDays] pd ON lsm.staffMemberId = pd.staffMemberId 

Этот запрос возвращает следующие результаты:

EmployeeName AbsenceDate HoursReported Status  TotalUsdHrs TotalRemingHrs 
X   11/11/2015  4   approved  4    76 
X   11/15/2015  8   approved  12   68 
X   11/20/2015  2   decline  14   66 
X   11/20/2015  2   approved  14   66 

Таким образом, запрос отлично работает для различного статуса. Первые 2 строки в порядке. Но когда сотрудник совершает более одного действия за день (отклонение, одобрение и т. Д.), Мой запрос показывает только общее количество использованных и общее количество оставшихся за день.

Вот ожидаемый результат.

EmployeeName AbsenceDate HoursReported Status  TotalUsdHrs TotalRemingHrs 
X   11/11/2015  4   approved  4    76 
X   11/15/2015  8   approved  12   68 
X   11/20/2015  2   decline  12   68 
X   11/20/2015  2   approved  14   66 

ответ

1

Вы делаете накопленную сумму, которая возвращает результаты на основе порядка AbsenceDate (sum(...) over (partition by ... order by pd.absenceDate). Но ваши последние 2 записи имеют ту же самую дату (11/20/2015) - по крайней мере, в соответствии с тем, что вы показываете нам. Это создает двусмысленность.

Таким образом, это абсолютно возможно, и юридическое, что SQL Server обрабатывает 2 approved hours строку перед тем в 2 declined hours строку при расчете кумулятивной суммы --which бы объяснить текущую results--, несмотря на то, что сами строки возвращаются вам в другом порядке (BTW, рассмотрите вопрос о добавлении в запрос предложения order by), в противном случае порядок самих строк не гарантируется).

Если две строки действительно имеют одну и ту же дату, вам нужно будет найти 2-й столбец, чтобы удалить двусмысленность и добавить это в пункт order by в общей функции окна sum. Возможно, вы можете добавить поле метки времени, которое вы можете заказать.

Или, возможно, вы всегда хотите, чтобы статус declined считался опереженным статусом approved, когда AbsenceDate - это то же самое. Вот пример запроса, который будет делать то, что (обратите внимание на изменения в order by статей):

SELECT  
    lsm.EmployeeName, 
    pd.absenceDate, 
    pd.amountInDays * 8 AS [HoursReported], 
    pd.status, 
    (SUM(CASE WHEN pd.[status]='App' THEN (pd.amountInDays * 8) 
       ELSE 0 END) OVER (partition by lsm.[EmployeeName] order by pd.absenceDate, 
                     case when pd.[status] = 'App' then 1 else 0 end)) AS [TotalUsedHours] 
      (@maxPSHours) - (sum(
       CASE WHEN pd.[status]='App' THEN (pd.amountInDays * 8) 
        ELSE 0 END) 
      over (
       partition by lsm.[EmployeeName] order by pd.absenceDate, 
                 case when pd.[status] = 'App' then 1 else 0 end)) AS [TotalRemainingHours] 
FROM  
    [LocationStaffMembers] lsm 
INNER JOIN 
    [PersonalDays] pd ON lsm.staffMemberId = pd.staffMemberId 
ORDER BY lsm.[EmployeeName], 
     pd.absenceDate, 
     case when pd.[status] = 'App' then 1 else 0 end 
+0

Я действительно не прочитал всю проблему ... но не обрамляющая окно с ' RANGE' исправить? – shawnt00

+0

@ shawnt00: Нет, я уверен, что это просто проблема с заказом. – sstan