Отсутствие T-SQL по месяцам с даты окончания даты начала - PullRequest
0 голосов
/ 30 января 2009

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

Им нужен отчет по месяцам о количестве пропусков (12-месячный тренд). С учетом того, что сотрудники не работают в течение месяца, это может быть трудно рассчитать.

например. Персонал с 25/11/08 по 05/12/08 (дд / мм / гг) Я хотел бы, чтобы ноябрьские дни учитывались в ноябрьских, а декабрьские - в декабрьских.

В настоящее время я думаю, чтобы подсчитать, сколько дней мне нужно разделить начальную и конечную дату в записи для каждого дня отсутствия, назначив ее для месяца, в котором она находится. Затем сгруппируйте данные для отчетности. Что касается тех без конечной даты, я бы предположил, что null - это текущая дата, так как они в настоящее время еще отсутствуют.

Как лучше всего это сделать?

Есть ли лучшие способы?

Редактировать: В настоящее время это сервер SQL 2000. Надеемся на обновление в ближайшее время.

1 Ответ

3 голосов
/ 30 января 2009

У меня была похожая проблема, когда существовала таблица дат начала / окончания, предназначенная для хранения данных, но не для отчетов.

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

DECLARE TABLE months (start DATETIME)
-- Populate with all month start dates that may ever be needed
-- And I would recommend indexing / primary keying by start

SELECT
    months.start,
    data.id,
    SUM(CASE WHEN data.start < months.start
            THEN DATEDIFF(DAY, months.start, data.end)
            ELSE DATEDIFF(DAY, data.start, DATEADD(month, 1, months.start))
        END) AS days
FROM
    data
INNER JOIN
    months
        ON data.start < DATEADD(month, 1, months.start)
        AND data.end > months.start
GROUP BY
   months.start,
   data.id

Это объединение может быть довольно медленным по разным причинам, я найду другой ответ на другой вопрос, чтобы показать, почему и как оптимизировать объединение.

EDIT:

Вот еще один ответ, касающийся перекрывающихся диапазонов дат и как ускорить объединение ...

Запрос максимального количества одновременных событий

...