Oracle: Как я могу определить, есть ли записи пропусков, основанные на поле даты? - PullRequest
0 голосов
/ 27 января 2012

У меня есть приложение, которое управляет расписаниями сотрудников.

Мои таблицы выглядят так:

TIMESHEET
  TIMESHEET_ID
  EMPLOYEE_ID
  etc

TIMESHEET_DAY:
  TIMESHEETDAY_ID
  TIMESHEET_ID
  DATE_WORKED
  HOURS_WORKED

Каждый период охватывает 14-дневный период, поэтому для каждой записи TIMESHEET имеется 14 записей TIMESHEET_DAY. И если кто-то уходит в отпуск, ему не нужно вводить расписание, если в течение этого 14-дневного периода не было рабочих часов.

Теперь мне нужно определить, есть ли у работников разрыв в 7 дней в предыдущие 6 месяцев. Это означает, что мне нужно искать либо 7 последовательных записей TIMESHEET_DAY с 0 часами, ИЛИ 7-дневный период с комбинацией отсутствия отправленных записей и записей, отправленных за 0 часов. Мне нужно знать DATE_WORKED последней записи TIMESHEET_DAY с часами в этом случае.

Приложение - asp.net, поэтому я мог бы извлечь все записи TIMESHEET_DAY и выполнить их итерацию, но я думаю, что должен быть более эффективный способ сделать это с SQL.

Ответы [ 2 ]

1 голос
/ 27 января 2012
SELECT t1.EMPLOYEE_ID, t1.TIMESHEETDAY_ID, t1.DATE_WORKED
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY  EMPLOYEE_ID, TIMESHEETDAY_ID ORDER BY DATE_WORKED) AS RowNumber,
            EMPLOYEE_ID, TIMESHEETDAY_ID, DATE_WORKED
      FROM (SELECT EMPLOYEE_ID, TIMESHEETDAY_ID, DATE_WORKED       
            FROM  TIMESHEET_DAY d
                  INNER JOIN TIMESHEET t ON t.TIMESHEET_ID = d.TIMESHEET_ID
            GROUP BY EMPLOYEE_ID, TIMESHEETDAY_ID, DATE_WORKED
            HAVING SUM(HOURS_WORKED) > 0) t ) t1
     INNER JOIN      
     (SELECT ROW_NUMBER() OVER(PARTITION BY  EMPLOYEE_ID, TIMESHEETDAY_ID ORDER BY DATE_WORKED) AS RowNumber,
            EMPLOYEE_ID, TIMESHEETDAY_ID, DATE_WORKED
      FROM (SELECT EMPLOYEE_ID, TIMESHEETDAY_ID, DATE_WORKED       
            FROM  TIMESHEET_DAY d
                  INNER JOIN TIMESHEET t ON t.TIMESHEET_ID = d.TIMESHEET_ID
            GROUP BY EMPLOYEE_ID, TIMESHEETDAY_ID, DATE_WORKED
            HAVING SUM(HOURS_WORKED) > 0) t ) t2 ON t1.RowNumber = t2.RowNumber + 1
WHERE t2.DATE_WORKED - t1.DATE_WORKED >= 7 
0 голосов
/ 27 января 2012

Я бы сделал это хотя бы частично с помощью SQL, подсчитав количество дней в расписании, а затем выполнил бы всю логику в программе.Это идентифицирует табели времени с пропущенными днями:

SELECT * FROM
    (SELECT s.timesheet_id, SUM(CASE WHEN d.hours_worked > 0 THEN 1 ELSE 0 END) AS days_worked
    FROM
        TimeSheet s
        LEFT JOIN TimeSheet_Day d
            ON s.timesheet_id = d.timesheet_id
    GROUP BY
        s.timesheet_id
    HAVING SUM(CASE WHEN d.hours_worked > 0 THEN 1 ELSE 0 END) < 14) X
    INNER JOIN TimeSheet
        ON TimeSheet.timesheet_id = X.timesheet_id
    LEFT JOIN TimeSheet_Day
        ON TimeSheet.timesheet_id = TimeSheet_Day.timesheet_id
    ORDER BY
        TimeSheet.employee_id, TimeSheet.timesheet_id, TimeSheet_Day.date_worked
...