Дополнительные примечания о моей структуре базы данных и некоторых случаях использования.
Дизайн стола
Это основная таблица (в основном на основе схемы iCalendar), в которой хранится событие. Событие может быть типичным событием или встречей, праздничным днем и т. Д.
event (event_id (PK), dtstart, dtend, ... --other icalendar fields--)
Если у события определенного типа есть дополнительная информация, которую я должен отслеживать, я украшаю ее другой таблицей. Например, в таблице для хранения электронной информации оставить конкретную информацию. (total_days не является вычисляемым полем как часть требований)
event_leave (event_id (PK/FK->event), total_days, leave_type_id (FK->leave_type))
Таблица типов отпуска хранит некоторую информацию о каждом типе отпуска. Например, требует ли приложение одобрения / рекомендации и т. Д. Кроме того, оно также хранит максимально допустимый перенос. Я предполагаю, что максимальный перенос не будет часто изменяться.
leave_type (leave_type_id (PK), name, require_support, require_recommend, max_carry_forward)
Пользователи делятся на группы, и каждой группе будет предоставлено количество дней, отведенных для отпуска, для некоторых от типа отпуска. Данные, хранящиеся в этой таблице, будут заполняться ежегодно (новая редакция для каждого года). Он хранит только количество отпусков для каждой группы , а не для каждого пользователя.
leave_allocation (leave_allocation_id, year(PK), leave_type_id (PK/FK->leave_type), total_days, group_id)
Следующая таблица для хранения информации о переносе. Эта таблица будет заполняться один раз в год для каждого пользователя . Эта таблица будет заполняться раз в год, так как расчет на лету не прост. Формула подсчета оставляемой_карты для пользователя:
leave_carry_forward(2009) = min(leave_allocation(2008) + leave_carry_forward(2007) - leave_taken(2008), maximum_carry_forward());
leave_carry_forward (leave_carry_forward_id, user_id, year, total_days)
Некоторые примеры использования и решения
Рассчитать баланс (WIP)
Для расчета баланса я делаю запрос к представлению, объявленному следующим образом
DROP VIEW IF EXISTS leave_remaining_days;
CREATE OR REPLACE VIEW leave_remaining_days AS
SELECT year, user_id, leave_type_id, SUM(total_days) as total_days
FROM (
SELECT allocated.year, usr.uid AS "user_id", allocated.leave_type_id,
allocated.total_days
FROM users usr
JOIN app_event._leave_allocation allocated
ON allocated.group_id = usr.group_id
UNION
SELECT EXTRACT(year FROM event.dtstart) AS "year", event.user_id,
leave.leave_type_id, leave.total_days * -1 AS total_days
FROM app_event.event event
LEFT JOIN app_event.event_leave leave
ON event.event_id = leave.event_id
UNION
SELECT year, user_id, leave_type_id, total_days
FROM app_event._leave_carry_forward
) KKR
GROUP BY year, user_id, leave_type_id;
Заполнить таблицу left_allocation в начале года
public function populate_allocation($year) {
return $this->db->query(sprintf(
'INSERT INTO %s (%s)' .
"SELECT '%s' AS year, %s " .
'FROM %s ' .
'WHERE "year" = %s',
'event_allocation',
'year, leave_type_id, total_days ...', //(all the fields in the table)
empty($year) ? date('Y') : $year,
'leave_type_id, total_days, ..', //(all fields except year)
$this->__table,
empty($year) ? date('Y') - 1 : $year - 1
))
->count() > 0; // using the database query builder in Kohana PHP framework
}
Заполнить таблицу left_carry_forward в начале года
Узнать тип отпуска, назначенный пользователю
Мне, вероятно, нужно переименовать это представление (я плохо умею называть вещи ...). На самом деле это таблица длявола для пользователя.
DROP VIEW IF EXISTS user_leave_type;
CREATE OR REPLACE VIEW user_leave_type AS
SELECT la.year, usr.uid AS user_id, lt.leave_type_id, lt.max_carry_forward
FROM users usr
JOIN app_event._leave_allocation la
JOIN app_event._leave_type lt
ON la.leave_type_id = lt.leave_type_id
ON usr.group_id = la.group_id
Фактический запрос
INSERT INTO leave_carry_forward (year, user_id, leave_type_id, total_days)
SELECT '{$this_year}' AS year, user_id, leave_type_id, MIN(carry_forward) AS total_days
FROM (
SELECT year, user_id, leave_type_id, total_days AS carry_forward
FROM leave_remaining_days
UNION
SELECT year, user_id, leave_type_id, max_carry_forward AS carry_forward
FROM user_leave_type
) KKR
WHERE year = {$last_year}
GROUP BY year, user_id, leave_type_id;